1. 理解函数声明
硬件将调用首地址为0位置的子例程
(*(void(*)())0)();
任何C变量的声明都由两部分组成:类型以及一组类似表达式的声明符,声明符从表面看与表达式有些类似,对它求值应该返回一个声明中给定类型的结果。
假定变量fp是一个函数指针,那么如何调用fp所指向的函数的调用方法如下:
(*fp)();
ANSI C标准允许程序员将上式简写为fp(),但是一定要记住这种写法只是一种简写形式。
我们一旦知道如何声明一个变量,也就自然知道如何对一个常数进行类型转换,将其转型为该变量的类型:知需要在变量声明中将变量名去掉即可。
硬件将调用首地址为0位置的子例程可读性更好的写法如下:
typedef void (*funcptr)();
(*(funcptr)0)();
signal函数接受两个参数:
- 一个整型的信号编号
- 一个指向用户定义的信号处理函数的指针
声明signal函数:
void (*signal(int, void(*)(int)))(int);
也可以使用typedef简化上面的函数声明:
typedef void (*HANDLER)(int);
HANDLER signal(int, HANDLER);
2. 运算符的优先级问题
优先级最高的并不是真正意义上的运算符,包括数组下标、函数调用操作符、结构成员选择操作符,括号,自左向右结合。
单目运算符优先级仅次于前述运算符,自右向左结合。
单目运算符中,算术运算符最高,移位运算符次之,关系运算符再次之,接着是逻辑运算符,赋值运算符,最后是条件运算符(实际上是三目运算符)
- 任何一个逻辑运算符的优先级低于任何一个关系运算符
- 移位运算符的优先级比算法运算符要低,但是比关系运算符要高
运算符==和!=的优先级要低于其他关系运算符的优先级
所有的赋值运算符优先级是一样的,而且它们的结合方式是右到左
在所有的运算符中,逗号的优先级最低
3. 注意作为语句结束标志的分号
4. switch语句
switch的case后需要加上break才会退出switch,不然会继续往下执行其他case,这个特性既是优势,也是一个弱点,但不使用break时,最好加上注释
5. 函数调用
C语言要求:在函数调用时即使函数不带参数,也应该包括函数列表。
6. 悬挂else引发的问题
else始终与同一括号内最近的未匹配的if结合
通过宏定义也可以悬挂else问题:
#define IF {if(
#define THEN ){
#define ELSE }else{
#define FI }}
使用过程如下:
IF x == 0
THEN IF y == 0
THEN error();
FI
ELSE z = x + y;
f(&z);
IF