《C缺陷与陷阱》阅读笔记-词法陷阱
1.1 = 不同于 ==
1.2 & 不同于 && | 不同于 ||
1.3 词法分析中的“贪心法”
编译器将程序分解成符号的方法是:每个符号应该包含尽可能多的字符。,需要注意的是,除了字符串和字符常量,符号的中间不能嵌有空白(空格符、制表符和换行符)。eg:下面的语句的本意似乎是用x除以p做指向的值,把所得的商再赋给y,
y = x/*p;
而实际上,/*被编译器理解为一段注释的开始,编译器将不断的读入字符直到*/出现为止。如果想按照本意,应该上面语句重写如下:
y = x / *p;
或者更加清楚一点:
y = x / (*p);
诸如此类的准二义性问题还有:
a=-1;
在老版本编译器中会解释为 a = a - 1;为保险起见,写为:
a = -1;
1.4 整型常量
如果一个整型常量的第一个字符是数字 0,那么该变量将被视为八进制数,需要注意的是有时候在上下文中为了格式对齐的需要,可能无意中讲十进制数写成了八进制数。
1.5字符与字符串
用单引号引起的一个字符其实代表一个整数,正数字对应于该字符在编译器采用的字符集中的序列值。因此,对一采用ASCII字符集的编译器而言,‘a’的含义与0141(八进制)或者97(十进制)严格一致。
用双引号引起的字符串,代表的却是一个指向无名数组起始字符的指针,该数组被双引号之间的字符以及一个额外的二进制为零的字符‘\0’初始化。下面的语句
printf("Hello\n");
与
char hello[] = {'H','e','l','l','o','\n',0};
printf("%s",hello);
char hello[] = {'H','e','l','l','o','\n',0};
printf("%s",hello);
是等效的。
在程序中使用字符串常量会生成“一个指向字符常量指针”。当一个字符串常量出现于一个表达式中时,表达式所使用的值就是这些字符所存储咋地址,而不是这些字符本身。因此,可以把字符常量赋值给一个“指向字符的指针”,后者指向这些字符所存储的地址。但是,你不能把字符串常量赋值给一个字符数组,因为字符串常量的直接值是一个指针,而不是这些字符本身。