The C Puzzle Book
2009-12-12
The C Puzzle Book
一、操作符:
1.+=,*=等符号是赋值符,优先级等同于=;
2.对于可能产生二义性的字符,如"x+++++y",C语言编译器将按照"构成操作符的字符个数越多越好"的原则来作出选择,于是有"x++ ++ +y";
3.对于“z = x / ++x”这样的表达式,编译器能给出不同的答案,这是由于C语言本身没有对这种情况作出规定;
4.定义宏
#define PRINT(int) printf("%dn",int)
可对任何int进行替换;
5.同上一条,若改写为
#define PRINT(int) printf(#int"=%dn",int)
则在C语言的预处理器中,#int将被替换成int 所代指的变量名,并将入合并入后面的双引号中;
6.在对二进制负数进行右移(>>),正负是不确定的,结果依编译器而定;
7.对式子
z+=x<y?x++:y++
的解读应为
z+=(x<y?x++:y++);
8.对操作符优先级来讲,&&是高于||的,而不是同等级别;同理,&,^,|也是递降的级别顺序;
二、头文件与预处理器:
1.合理地使用宏定义,可以使程序简洁,编程方便,但使用不恰当常会带来难以调试的错误,在分析此类问题时,应把替换内容重现出来才更容易看出原因;
2.使用宏有如下规则:
1)只要一条宏定义语句是包含有操作符的,就应该用括号把它括起来;
注:特别是对于*,/,for(..,..,..),if(..)else(..)等符号语句,只读取与之相关联的一个字符或语句,更容易出问题。
2)宏定义越紧凑越好,表达式比语句好,单条语句比多条语句好;
注:在定义时可将";"替换为",",使结构更紧凑。
3)在宏定义里一定要注意避免使用会导致二义性或副作用的C语言元素(如自增自减);
3-1)在定义里避免使用有副作用的表达式,比如:这些元素在宏定义语句里只出现一次,但在实际扩展中可能会出现多次,将使结果错误;
4)一定要让宏进行扩展而得到的字符串——不管它是一个表达式,一条语句(不包括表示语句结束的分号),还是一个语句块——成为一个完整的C语言元素;
注:若有else不对称问题,可以在定义中加上空的else子句。
5)宏越简单越好。如果无法得到一个简单的宏,就应该把它定义成一个函数;
注:##字符可以合并它的两个操作数。