尽管字符类型(尤其是无符号字符型) 可以当成“小” 整型使用, 但由于不可预知的符号扩展和代码增大有时这样做可能得不偿失。
定义是分配空间并赋初值(如果有) 的声明。
永远不要把外部函数的原型放到.c 文件中: 通常它与定义的一致性不能得到检查, 而矛盾的原型比不用还糟糕。
在extern int f();和int f();之间并没有实质的区别。
使用cdecl 程序, 它可以把英文翻译成C 或者把C 翻译成英文
一本好的C 语言书都会解释如何“从内到外” 解释和理解这样复杂的C 语言声明(“模拟声明使用”)。
在范围内没有声明就调用(可能是第一次调用在函数的定义之前) 的函数被认为返回整型(int) (且没有任何参数类型信息), 如果函数在后边声明或定义成其它类型就会导致矛盾。所有函数(非整型函数一定要) 必须在调用之前声明。
calloc() 获得的内存为全零, 但这对指针和浮点值不一定有用
以下的初始化有什么区别?char a[] = “string literal”; char *p = “string literal”; 当我向p[i] 赋值的时候, 我的程序崩溃了。
字符串常量有两种稍有区别的用法。用作数组初始值(如同在char a[] 的声明中), 它指明该数组中字符的初始值。其它情况下, 它会转化为一个无名的静态字符数组, 可能会存储在只读内存中, 这就是造成它不一定能被修改。在表达式环境中, 数组通常被立即转化为一个指针, 因此第二个声明把p 初始化成指向无名数组的第一个元素。
int (*fp)() = func;
这样声明结构的代码: struct name { int namelen; charnamestr[1];}; 然后又使用一些内存分配技巧使namestr 数组用起来好像有多个元素。这种技术十分普遍。这些“亲密” 结构都必须小心使用, 因为只有程序员知道它的大小, 而编译器却一无所知。
C99 引入了“灵活数组域” 概念, 允许结构的最后一个域省略数组大小。这为类似问题提供了一个圆满的解决方案。
如何向接受结构参数的函数传入常数值?
传统的C 没有办法生成匿名结构值; 你必须使用临时结构变量或一个小的结构生成函数。
C99 标准引入了“复合常量” (compound literals); 复合常量的一种形式就可以允许结构常量。例如, 向假想plotpoint() 函数传入一个坐标对常数, 可以调用plotpoint((struct point){1, 2});
与“指定初始值” (designated initializers) (C99 的另一个功能) 结合, 也可以用成员名称确定成员值:plotpoint((struct point){.x=1, .y=2});
如何确定域在结构中的字节偏移?
ANSI C 在<stddef.h> 中定义了offsetof() 宏, 用offsetof(struct s, f) 可以计算出域f 在结构s 中的偏移量。如果出于某种原因, 你需要自己实现这个功能, 可以使用下边这样的代码:
#define offsetof(type, f) ((size_t)
((char *)&((type *)0)->f – (char *)(type *)0))
这种实现不是100% 的可移植; 某些编译器可能会合法地拒绝接受。
a[i] = i++; 不能工作
表达式: a ˆ= b ˆ= a ˆ= b不具有可移植性。它试图在序列点之间两次修改变量a, 而这是无定义的。
如果一个表达式和程序变得未定义, 则它的所有方面都会变成未定义。