现在的位置: 首页 > 综合 > 正文

嵌入式linux-C学习之基础

2018年01月22日 ⁄ 综合 ⁄ 共 4006字 ⁄ 字号 评论关闭

1、数据类型的转换:

转换有两种:(1)自动转化:遵循一定的规则,有编译系统自动完成,自动转换规则:由低到高:char,short——>int——>unsigned——>long——>double<——float

                         (2)强制类型转换:把表达式的运算结果强制转换成所需要的数据类型,例如:(int)(a+b);把a+b的结果转化为整型


3、bool变量与“零值”进行比较

if( !b_test_flag )或者if(b_test_flag);


4、float变量与“零值”进行比较

if((f_test_val >= -0.00000001) && (f_test_val <= 0.00000001)

float和double类型的数据都是有精度限制的,这样直接拿来与0.0比,必须像上面语句那样


5、指针变量和“零值”进行比较

if(NULL == p);  if( NULL != p);


6、case语句后面不要忘记加上break;

记住:case后面只能是整型变量、字符型、常量或者常量表达式

const修饰的数据不能用在case后面


7、循环语句的注意点:

(1)在多重循环中,如果有可能,应当将最长的循环放到最里面,最短的放到最外面,以减少CPU跨切循环层的次数。相对来说循环效率高


8、goto语句我主张的应该想内核一样使用:

在实现功能上尽量不要用,

例如:

int  fun(void)

{

int i=0;

if(i == 0)

goto error;

else

{

......

}

error :

return -1;

}


9、const关键字也许该被替换为readolny

const是congstant的缩写,是恒定不点的意思,也翻译成常量、常数等。

基于这一点很多人都认为被const修饰的值是常量,这是不精确地,精确地说应该是只读的变量。其值在编译的时不能被使用,因为编译器在编译时不知道其里面存储的什么内容。

const修饰的只读变量必须在定义的同时初始化,同时它存放在静态去,也就是全局变量去,

编译器通常不为普通const只读变量分配存储空间,而是将它们保存在符号表中,这样使得它成为一个编译期间的值,没有了存储与读内存的操作,使得效率也很高。


这里看看和define的区别:例如下面:

#define M 3     //宏常量

const int N=5;  //此时并为将N放入内存中


int  i=N;    //此时为N分配内存,以后不再分配

int  i = M;  //预编译期间进行宏替换,分配内存

int  j = N;    //没有内存分配

int  j = M;     //再进行宏替换,又一次分配内存,

 

修饰指针:

const int *p;        //p可变,p指向的对象不可变

int const  *p;       //p可变,p指向的对象不可变

int *const p;        //p不可变,p指向的对象可变

const int * const p;    //指针p和o指向的对象都不可变

这里给出一个记忆方法:

先忽略类型名(编译器解析的时候也是忽略类型吗,我们看到离cost离那个就近,离谁近就修饰谁




10、volatite 是一边的、不稳定的意思,   也很少用。


11、union 关键字

union维护足够的空间来置放多个数据成员中的”一种“,而不是为每一个数据成员配置空间,在union中所有的数据成员公用一个空间,同一时间只能存储其中一个数据,所有的数据成员具有相同的起始地址,例如:

union machine

{

char character;

int num;

char *str;

double exp;

};

一个union只配置一个足够大的空间以来容纳最大长度的数据成员,以上栗二样,最大的是double类型,所以machine的空间大小为double 数据类型的大小。


大、小端模式对union的影响:

union

{

int i;

char a[2];

}*p,u;

p=&u;

p->a[0]=0x38;

p->a[1]=0x30;

p.i的值应该为多少呢?

这里需要考虑存储模式:大端模式和小端模式。

union类型数据所占的空间等于其最大成员所占的空间,对union类型的成员的存储都是相对该联合体基地址的偏移量为0处开始,也就是联合体的访问不论对那个变量的存取都是从union的首地址位置开始,


12、enum关键字

很多初学者对枚举感到迷惑,或者认为没有什么用,其实枚举(enum)是个很有用的数据类型。

(1)使用方法:一般定义如下:

enum enmu_type_name

{

ENUM_CONST_1,

ENUM_CONST_2,

.....

}enum_variable_name;

注意: enum_type_name是自定义的一种数据数据类型名,而enum_variable_name为enum_type_name类型的一个变量,也就是我们平时常说的枚举变量,实际上enum_type_name类型是对一个变量取值范围的限定,而花括号内是他的取值范围,即
enum_type_name类型的变量enum_variable_name 只能取值为花括号内的任何一个值,如果赋给该类型变量的值不在列表中,则会报错或者警告。ENUM_CONST_1 、ENUM_CONST_2 、... 、
ENUM_CONST_n ,这些成员都是常量,也就是我们平时所说的枚举常量(常量一般用大写)。enum 变量类型还可以给其中的常量符号赋值,如果不赋值则会从被赋初值的那个常量开始依次加1 ,如果都没有赋值,它们的值从 0 开始依次递增1。

例如分别用一个常数表示不同的颜色:

enum Color

{

GREEN= 1,

RED,

BLUE,

GREEN_RED=10,

GREEN_BLUE

}ColorVal

其中个常量名代表的数值分别为:

GREEN=1

RED=2

BULE=3

GREEN_RED=10

GREEN_BULE=11

枚举与#define宏的区别

下面看看枚举与#define宏区别:

(1)#define 宏常量是在预编译阶段进行简单的低缓,枚举常量是在编译的时候确定的

(2)一般在编译器里,可以调试枚举常量,但是不能吊事宏常量

(3)枚举可以一次定义大量相关的常量,而#define宏一次只能定义一个,


13、typedef

typedef的真正意思是给一个已经存在的数据类型(注意:是类型,不是变量)取一个别名,而非定义一个新的数据类型,在实际项目中,为了方便,可能很多数据类型(尤其是结构体之类的自定义数据类型)需要我们重新取一个适用实际情况的别名。这时候typedef就可以帮忙了:如下例:

typedef struct student 

{

//code

}Stu_st,*Stu_pst;

对struct student *stu2;  和  Stu_pst stu2;  和Stu_st *stu2     // 没有区别


在如下面的:

(1)#define INT32  int

unsigned INT32 i=20;

(2)typedef int int32;

unsigned int32 j=20;

其中(2)编译出错,为什么,因为#define编译的时开始宏替换,替换为int 所以(1)正确,那么(2)typedef取别名不支持这种类型扩展,

下面再看看一个与#define宏有关的例子:

(3)#define pch char*

pch p3,p4;

(4)typedef char* pchar;

pchar p1,p2,

两组代码编译都没问题,但是,这里的p4却不是指针仅仅是一个char类型的字符,这种错误很容易被忽略,所以用#define的时候要慎之又慎,

14、关于注释:

编译器在编译的时候会把注释符号剔除掉,用空格代替原来的注释符

对于全局变量、常量以及函数必须加注释。

在C语言里面 \ 表示断行,\后面不许有空格,同时\也表示转义字符

15、左移和右移 <<  、>>

0x01>>2+32;对吗?

显然不对,由于整型数长度为32位,右移32位发生什么了!溢出,所以左移和右移的位数是有讲究的。左移和右移的位数不能大于数据的长度,不能小于0。


16、函数:

(1)如果参数是指针,且仅作为输入参数怎应在类型前加const,以防止指针在函数体内被意外修改

例如:void str_copy(char *str_destination,const char *str_source);

(2)如果没写函数返回类型,那么编译器默认的函数返回类型为int 型。

(3)return语句不可返回指向“栈内存”的“指针”,

例如:

char * fun(void)

{

char str[20];

.......

return str;

}

(4)尽量避免函数带有“记忆”功能,在C语言中,函数的static局部变量是函数的“记忆”存储器,建议尽量少用

static 定义局部变量,除非必需。

(5)函数递归

编写一个测试字符串长度的函数。不使用局部、全局变量也不调用库函数,

int my_strlen(const char *str_dest)

{

assert(NULL != str_dest);

if('\0' == *str_dest)

{

return 0;

}

else

{

return (1 + my_strlen( ++str_dest ));

}

}








2、变量命名:以字符或者下划线开头,由字符、下划线和数字组成;

sizeof:他是求变量的类型所占的内存大小,例如:int int_a=100;sizeof(int_a)结果为:4,因为int类型占内存空间4个字节,而不是100。其中数组int b[10]={0};它所占的空间为40个字节,

对结构体来说:例如:

strcut student

{

       int a;

       char p;

} type ; 它所占的字节为8,不知道其中的道理,那就自己解决吧! ^_^ 。

 

 

                                 

                                      

 

 

抱歉!评论已关闭.