第七章
1.null指针并不指向任何对象,所以只用于赋值和比较运算,其他使用目的都是非法的。
误用null指针的后果是未定义的,根据编译器各异。
有的编译器对内存位置0只读,有的可读写。
书中给出了一种判断编译器如何处理内存0的代码:
#include <stdio.h>
int main()
{ char *p;
p=NULL;
printf("location 0 contains: %d\n", *p); return ;
}
在禁止读内存0的机器上,程序会执行失败。有的机器上,却可以10进制打印内存0存储的字符内容。
笔者试了下codeblocks,程序执行失败,即禁止读内存0.
2.移位运算符
在向右移位时,会考虑空出的位是0填充,还是符号位填充?
如果移位对象是无符号数,毫无疑问是0填充;若是有符号数,可以是0填充也可以是符号位。
具体负数的移位操作下次专门写一篇。
移位操作的位数限制在被移位对象的长度内。
即若int型是32位,n是int型,那么[0-31]的移位时合法的:n<<31, n<<0
3.大小写转换
库函数 toupper tolower起初被定义为:
#define toupper(c) ((c)+'A'-'a')
#define tolower(c) ((c)+'a'-'A')
但是这个宏定义没考虑输入的大小写是否正确。
如下程序将不能工作:
int c;
while ((c)= getchar() != EOF)
putchar(tolower(c));
应该改为:
int c;
while ((c)= getchar() != EOF)
putchar(isupper(c) ? tolower(c) : c);
或者重写函数,如 toupper:
int toupper (int c)
{
if (c >= 'a' && c <= 'z')
return c + 'A'-'a';
return c;
}
这样的程序更加健壮,就是函数调用相比宏定义更加浪费开销。
至此 C陷阱与缺陷 的读书笔记就结束了,感觉该书知识有点旧但讲的很有深度,对于大型C项目和多平台项目有启发!