嵌入式C语言可靠性设计


花了两天才把《涨姿势!高手带你全面了解嵌入式C语言可靠性设计》这篇文章读完(有时候没集中精神去看直播直播这东西真的害人)

下面列出我从中学到的几点:

1.编译器不可能无视的错误:不可给常量赋值。所以通常写成if(5==x){...}
2.使用switch...case语句时,要在合适的位置添加break关键字
3.break关键字用于跳出最近的那层循环语句或者switch语句
4.8进制常量以'0'为前缀
5.指针的加减运算是特殊的。如:
int *p=(int*)0x00001000;
p=p+1;
运算结果为p=0x000010004。指针在做加减运算时是以指针的数据类型为单位,即p+1实际上为p+1*sizeof(int)
6.sizeof()
(1)是一个关键字,不是函数,默认返回无符号的整形数据
(2)使用sizeof获取数组长度时,不要对指针使用sizeo操作
7.当数组作为函数形参时,数组名被认为是指针
8.在C语言中允许使用类似a[-1]形式来快速获取数组首元素所在地址前面的数据
9.允许将个常数强制转换为函数指针,使用代码(*((void(*)())0))()来调用位于0地址的函数。
10.无符号char类型表示范围为0~255永远小于256大于等于0
11.由于不是所有编译器都对数组越界足够敏感,所以当一个数组声明为具有外部链接,它的大小应该显式声明
12.数组和指针容易造成混乱
13.在通讯中,若接收的数据超出数组范围,多于的数据改写与数组相邻的变量,造成系统崩溃
14.如果局部数组越界,可能引发ARM架构硬件异常崩溃
15.限定符volatile在嵌入式软件中至关重要,用来告诉编译器不要优化它修饰的变量
16.由于寄存器速度远快于RAM,编译器在使用非volatile限定变量时是先将变量从RAM中拷贝到寄存器中,如果同一个代码块再次用到该变量,就不再从RAM中拷贝数据而是直接使用之前寄存器备份值
17.局部变量必须显示初始化,否则无法保证局部变量初始值为0
18. 编译器会在第一次运行时清零堆栈区
19.不合理的#define会引起重优先级的问题


常被误会的

优先级

表达式 常被误认为: 其实是:
取值运算符*与自增运算符++优先级相同,但它们是自右向左结合 *p++ (*p)++ *(p++)
成员选择运算符.高于取值运算符* *p.f (*p).f *(p.f)
数组下标运算符[]优先级高于取值运算符* int *ap[]

int (*ap)[]

ap为数组指针

int *(ap[])

ap为指针数组

函数()优先级高于取值运算符* int * fp()

int (*fp)()

fp为函数指针

int * (fp())

fp为函数,返回指针

等于==和不等于!=运算符优先级高于位操作运算符&、^ 和 | val & mask != 0 (val & mask)!= 0 val &(mask != 0)
等于==和不等于!=运算符高于赋值运算符= c=getchar()!=EOF (c=getchar())!=EOF c=(getchar()!=EOF)
算数运算符+和-优先级高于移位运算符<<和>> msb<<4+lsb (msb<<4)+lsb msb<<(4+lsb)

20.当出现在表达式里时,有符号和无符号的char和short类型都将自动被转换为int类型,在需要的情况下,将自动被转换为unsigned int(在short和int具有相同大小时)
21.如果位运算符 ~ 和 << 应用在基本类型为unsigned char或unsigned short 的操作数,结果应该立即强制转换为unsigned int或者unsigned short类型
22.在包含两种数据类型的任何运算里,两个值都会被转换成两种类型里较高的级别
类型级别从高到低的顺序是long double>double>float>unsigned long long>long long>unsigned long>long>unsigned int>int
23.当作为函数的参数被传递时,char和short会被转换为int,float会被转换为double

你可能感兴趣的:(成都学习)