C语言缺陷与陷阱(3)

时间:2022-06-03 16:06:05

语义分析

(程序员本意是希望表示某种事物,而实际表示的却是另外一种事物)

1.     指针和数组

数组值必须注意的两点:(1)C语言只有一维数组,且数组大小必须在编译期作为一个常数确定下来;(2)对一个数组只能进行:确定该数组的大小,以及获得指向该数组下标为0的元素的指针

若一个指针指向的是数组中的一个元素,那么给该指针加1就能够得到该数组中下一个元素的指针,该该指针减1就能够得到该数组中上一个元素的指针。

只有在两个指针指向同一个数组中的元素时,对两个指针相加、减才有意义。

2.     非数组的指针

对于字符串常量,不但包括字符串中所有字符,还包含一个空字符(’\0’的内存区域地址。

在进行常量字符串的复制等操作时,要注意:(1)利用malloc申请分配的内存是否成功;(2)分配的内存使用之后应及时释放;(3)分配内存的大小应为strlen(str)+1

3.     作为参数的数组声明

使用数组名作为参数,那么数组名会立刻被转换为指向该数组第一个元素的指针

如果指针参数为一个数组,则表示指向某一数组的起始元素的指针。

4.     避免“举隅法”(以含义更宽泛的词语来代替含义相对较窄的词语,或者相反。如以整体代表部分,或者以部分代表整体)

复制指针并不同时复制指针所指向的数据

5.     空指针并非空字符串

常数0被转换为指针使用时,这个指针绝对不能被解除引用。即,当将0赋值给一个指针变量时,绝对不能企图使用该指针所指向的内存中存储的内容。

6.     边界计算与不对称边界

在C中,一个数组有N个元素,则其下标从0~N-1.为了避免数组越界、“栏杆错误”等情况的发现,最好的处理方法是:用第一个入界点第一个出界点来表示一个数值范围。

在处理循环时,运用--n>=0的效率比较高

7.     求值顺序

在C中,只有&&||?:,存在规定的求值顺序。

&&和||先对左侧操作数求值,只在需要时才对右侧操作数求值;

在a?b:c,先对a求值,根据a 的值再求bc的值;

,(逗号运算符),先对左侧操作数求值,然后该值被“丢弃”,再对右侧操作数求值。(注意:分隔函数参数的逗号并非逗号运算符)

8.     运算符&&、||和!

按位运算符&|~对操作数处理的方式是:将其视作一个二进制的位序列,分别对其每个位进行操作。(注意:负数的表示为其补码);

逻辑运算符&&||!对操作数处理的方式是:将其视作要么是“”,要么是“”。

9.     整数溢出

无符号算术运算中,没有所谓的溢出;

若算术运算符的一个操作数是有符号整数,另一个无符号整数,那么有符号整数会被自动转换无符号整数;

若算术运算符的两个操作数都是有符号整数,溢出有可能发生,但溢出的结果是未定义的

10.  为函数main提供返回值

在C中main函数返回类型默认为整型,通过main函数的返回值来告知操作系统该函数的执行是成功还是失败。一般情况下,返回0代表程序执行成功,返回非0代表程序执行失败。