C语言进阶:C陷阱与缺陷(读书笔记总)

您所在的位置:网站首页 统计陷阱读书报告800字内容 C语言进阶:C陷阱与缺陷(读书笔记总)

C语言进阶:C陷阱与缺陷(读书笔记总)

2024-07-10 18:05| 来源: 网络整理| 查看: 265

大家不要只收藏不关注呀,哪怕只是点个赞也可以呀!🤣 粉丝私信发邮箱,免费发你PDF!!!

最近读了一本C语言书《C陷阱与缺陷》,还不错,挺适合刚刚工作后的人,特此分享读书笔记,写代码时应注意这些问题,笔记已做精简,读完大概需要30min。如果读起来感觉很吃力,那我推荐你读一读书,书上的例子比较多,看着能轻松一点,老鸟看起来应该不是很难,作为复习一下,应该还不错,如果需要pdf文档,请私信我,我发给你,这本书今天读完了,说一下感受,如果只是入门的话,读完感受并不强烈,如果在工作了一段时间后,就会发现书中的错误确实是新手容易犯而且一些之前不理解的地方确实有了更新的认识,值得一读。

C陷阱与缺陷 一、词法陷阱1、= 不同于 ==2、&和|不同于&&和||3、单字符符号与多字符符号4、整形常量5、字符与字符串 || 二、语法陷阱1、理解函数声明2、运算符的优先级问题3、注意作为语句结束标志的分号4、switch语句5、函数调用6、悬挂 else引发的问题 三、语义陷阱1、 指针与数组2、 非数组的指针3、 作为参数的数组声明4、 避免”举隅法“5、 空指针并非空字符串6、 边界计算与不对称性7、 求值顺序8、 运算符&&、|| 和 !9、 整数溢出10、 为函数main提供返回值 四、 连接1、 什么是连接器2、声明与定义3、命名冲突与static修饰符4、形参、实参与返回值5、 检查外部类型6、 头文件 五、 库函数1、 返回整数的getchar函数2、更新顺序文件3、缓冲输出与内存分配4、 使用errno检测错误5、 库函数signal 六、 预处理器1、 不能忽视宏定义中的空格2、 宏并不是函数3、 宏并不是语句4、 宏并不是类型定义 七、 可移植性缺陷1、 应对C语言标准变更2、 标识符名称的限制3、 整数的大小4、 字符是有符号还是无符号整数5、 移位运算符6、 内存位置为07、 除法运算时发生的截断8、 随机数的大小9、 大小写转换10、 首先释放、然后重新分配 八、 建议1、通用建议

一、词法陷阱 1、= 不同于 ==

将比较值放在左边,变量放到右边,例如if(NULL==p->s)

2、&和|不同于&&和||

按位运算符 &(相同1才取1) 和 |(有一个1便为1) ;逻辑运算符 &&(and)和|| (or) ; 0111 1101 & 1111 0000 =0111 0000 ;0111 1101 |1111 0000 = 1111 1101 If(a>10&&b10) if(a>10 || b10)

3、单字符符号与多字符符号

每个符号应该包含尽可能多的字符:从左到右一个一个字符读入,如果字符组成一个符号,那么再读入下一个字符,判断已经读入的两个字符串是否可能是一个符号的组成部分,如果可能,继续上面的判断,知道读入的字符不再可能组成有意义的符号。 例如:(a*(b+c))) a—b 与a-- -b 含义相同,但与 a- --b含义不同,y = x /*p 这里是会出现错误,应该写作y= x / *p ;或者y = x /(*p)

4、整形常量

如果一个整形常量的第一个字符是0,那么该常量将被视作8进制数。因此,10和010的含义截然不同,转换为十进制 1010,0108

5、字符与字符串 ||

字符用 char hello[ ]={‘h’,’e’,’l’,’l’,’o’,’\n’} 与 char hello[ ] ={“hello\n”} 等效

二、语法陷阱 1、理解函数声明

当计算机启动时,硬件将调用首地址为0位置的子例程 假设fp是一个指向返回值为void类型的函数的指针。 void (fp) (); (fp) (); 对常数进行一个类型转换,将其转型为该变量的类型,如将常数0,转型为 “指向返回值为void的函数的指针”类型,如( void () () ) 0 用( void () () ) 0替换fp (( void () () ) 0) ();

2、运算符的优先级问题

逻辑运算符(&& 、||)的优先级低于关系运算符(>、big); Big =x[i];

if(x[i]>big) Big =x[i]; 截然不同。

还例如

If(n0 ? a : -a+1 但我们的本意不是这样。 如果宏实现比较复杂,那么尽量使用函数来实现。 宏的展开可能会产生庞大的展开式。

3、 宏并不是语句

这里的例子有点晦涩,不知如何表达,只是记住宏并不能直接当作语句去使用,并且要注意分号即可。

4、 宏并不是类型定义 #define FOOTYPE struct foo FOOTYPE a; FOOTYPE b,c;

这样我们只需要修改一行代码就可以改变abc的类型,但是我们并不推荐如此使用,最好还是使用类型定义

typedef struct foo FOOTYPE; 七、 可移植性缺陷

因为编译环境的不同,可移植性就成了一个重要话题,本节讨论几个最常见的错误来源。

1、 应对C语言标准变更

新标准无法在旧编译器中使用,为了增强可移植性,我们最好的做法在旧的环境和新的环境收益中做好选择。

2、 标识符名称的限制

不要用大写的函数名称与库函数同名,例如malloc和Malloc,假如你自己写的是Malloc,但是编译器如果不区分外部名称大小写,这里就会出错,要避免这种情况。

3、 整数的大小

非正式情况下short 与 int 是16位 long 是32位,这与机器的字符长度有关。 可移植性最好的办法就是声明该变量为long型,但在这种情况下我们去定义一个新的类型更加清晰:例如

typedef long tenmil; 4、 字符是有符号还是无符号整数

将char型转换为int型需要做出选择;如果要转换为有符号数,那么编译器将char类型扩展为int 型时需要复制符号位,如果是转换为无符号数,那么编译器只需要在多余的位上直接填充0即可。如果最高位是1,那么将这数定义成为无符号字符 ,无论什么编译器,在该字符转换为整型时都只需在多余的位填充0即可。 一个常见错误:如果c是一个字符变量,使用(unsigned)c 强制类型转换成无符号整型,这里会出现错误。因为转换为无符号时,会先转换为int型,这里会得到非预期的结果。 正确的方法是(unsigned char)c;

5、 移位运算符

在向右移位时,空出的位是由0填充还是由符号位的副本填充? 如果将操作的变量声明为无符号类型,那么空出的位是由0填充,如果是有符号位,那么二者都可以。 移位计数(即移位操作的位数)允许的取值范围是什么? 如果被移位的对象是n位,那么移位计数应该大于0且小于n,为什么要加这个限制,因为加上这个限制后,我们就能够在硬件上高效地实现移位运算。

6、 内存位置为0

null指针并不指向任何对象,除非是用于赋值或比较运算,出于其他任何目的使用null指针都是非法的。

7、 除法运算时发生的截断

q=a/b r=a%b 性质1:q*b+r==a;性质2:如果改变a的正负号,我们希望只改变q的符号,但不改变q的绝对值;性质3:当b>0时,我们希望r>=0且r



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3