【C】专家编程 (Expert C Programming) 阅读笔记

发布时间 2023-06-18 11:24:26作者: 徐大树

 

 
第一章 C:穿越时空的迷雾
 

 

1 p22 ~ 24  ANSI C 有此问题。
“安静”的类型转换原则:当执行算术运算时,操作数的类型如果不同,就会发生转换。数据类型一般朝着浮点精度更高,长度更长的方向转换,整形术如果转换为 singed 不会丢失信息,就转换为 signed,否则转换为 unsigned。
 
unsinged int a = 1;
int b = -1;
if (b < a) {
    printf(“yes \n");    
} else {
    printf(“no \n”);  //运行结果是这个!!!
}
 
If 语句在 signed 和 unsigned int 之间测试相等性,b 被升级为 unsighed int,因而变成了一个很大的正整数,所以条件为假。如果转换 a 为 int 类型,再比较,不会有问题。
 
小启发: 
尽量不要在你的代码里使用无符号类型,以免增加不必要的复杂性。尤其是,不要仅仅因为无符号数不存在负值(如年龄,国债)而用它来表示数量。
只有在使用位段和二进制掩码的时候,才使用无符号数。应该在表达式中强制类型转换,是操作数同时为有符号数或无符号数,这样就不必由编译器选择结果类型。
 
 
第二章 这不是Bug,而是语言特性
 
1 p40 小启发:x = f() + g() * h();  f,g,h 的计算顺序是不确定的,被称为 意群的计算顺序。这个顺序是未定义的,目的是让编译器充分利用自身架构的特点。编程时,一定不要依赖意群的计算顺序。类似的还有函数中,参数如果是表达式,计算顺序也不确定。
 
2 p42 用 fgets 取代 gets 函数,由于 gets 没有限制输入的长度,也没有检查,所以很容造成溢出。 fgets 由于限制了长度,可以防止这个问题发生。但标准里没有去掉 gets 方法。
 
3 p45 shell 或者 C 程序的参数中,要注意 “-” 字符。因为 “-” 往往被理解成参数,例如:“ls -l”。但有时候,你的参数真的只是以 “-” 开头而已,这样却会导致一些错误。比如:grep “-happy”。注意,在运行普通C程序,进行手动参数解析的时候,尤其要注意这一点。
 
4 p49 由函数的调用者来分配内存,在同一代码块中进行 malloc 和 free 操作,内存管理是最轻松的。
 
5 p51 尽量使用 lint 程序检查代码。虽然许多人认为应该把 lint 作为一个独立的工具,但是作者认为 独立 = 束之高阁。
 
 
第三章 分析 C 语言的声明
 
1 p58 声明是如何形成的:
 

 

 

 

 
2 p63 声明的分析:
 

 

 

 

 
一个分析的示例:
 

 

 
对上面解析的一点解释:
 

 

3 p68 typedef