1. 一段代码,第一次执行时的行为与以后执行时不同:
1 generate_initializer(char * string) 2 { 3 static char separator = ‘ ‘; 4 printf("%c %s \n", separator, string); 5 separator = ‘,‘; 6 }
可用于自动生成列表。
2. 函数的可见性
1 function apple() { /* 在任何地方均可见 */ } 2 extern function pear() { /* 在任何地方均可见 */ } 3 4 static function peach() { /* 在这个文件之外不可见 */ }
3. 这个语句p = N * sizeof * q;当中的乘号有几个?一个还是两个?
答案是一个。因为sizeof的操作数是类型名的时候,两边必须加上括号,但操作数如果是变量,则不必加括号。
那这个语句呢:apple = sizeof(int) * p;
是int类型的长度乘以p呢,还是?
4. 优先级的问题
*p.f是*(p.f),对p取f偏移作为指针,再解引用。
int *ap[]是int *(ap[]),指针的数组。
int *fp()是int *(fp()),函数指针。
val & mask != 0 是val & (mask != 0)。
c = getchar() != EOF是c = (getchar() != EOF)
msb << 4 + lsb是msb << (4 + lsb)
i = 1, 2是(i = 1), 2
5. 记住,在优先级和结合性规则告诉你哪些符号组成一个意群的同事,这些意群内部如何进行计算的次序始终是未定义的。在这个表达式里:
x = f() + g() * h();
乘法比加法优先级高,但是f()、g()、h()的调用次序是未定义的。
6. gets()函数对读入的字符数未做检查,容易导致缓冲区溢出。所以我们应该用fgets()彻底取代gets()。
char *fgets(char * restrict s, int n, FILE * restrict stream);
7. ANSI C规定编译器词法分析中采取maximal munch strategy策略,选取能组成的最长字符序列的方案。
所以z = y+++x就被解释为z = y++ + x;
那么z = y+++++x呢?它被解释为z = y++ ++ +x,引发编译错误。因为y++返回的是右值,而自增操作只支持左值。
8. 作者给出了
a //*
//*/ b
这个例子,说在C语言里表示a/b,在C++里表示a。
但是ANSI C的新标准已经将//当成了C的行注释符号。所以这个例子已经不适用。
9. 返回一个字符串的几种方案:
返回一个指向字符串常量的指针;(不能被改写)
使用全局声明的数组;(浪费空间)
使用静态数组;(不可重入,且同样耗费空间)
在函数内显式动态分配内存,保存返回的值;(程序员必须回收内存)
要求调用者分配内存来保存函数的返回值,同时指定缓冲区的大小(like fgets())。