【C语言】三剑客之《C陷井与缺陷》完整笔记

《C陷井与缺陷》1.2 进制陷井1.3 字符与字符串陷井 第2章:语法陷井 第3章:语义陷井 第4章:连接 第5章:库函数 第6章:预处理器 第7章:可移植性缺陷
前言第1章:词法陷井 1.1运算符陷井 1.1.1 =不等于==1.1.2 &和| 不同于 &&和||1.1.3 “贪心法”1.2 进制陷井
struct {int a;char *b;}para[] ={045, "one"086, "two"125, "three"};
1.3 字符与字符串陷井第2章:语法陷井 2.1 函数声明2.2 运算符优先级2.3 分号2.4 语句
switch(2){case 1:printf("red ");case 2:printf("yellow ");case 3:printf("blue ");}输出yellow blue
这一特性是C的弊端也是C的优势 , 优势是功能和操作码可以一对多 , 或者多对一 , 变得更加灵活
【【C语言】三剑客之《C陷井与缺陷》完整笔记】switch(ch){case '\n': //换行linecont++;case '\t': //制表case '': //空格……//处理 , 跳过空白符}
这里三种空白字符的处理是一样的 , 同时遇到换行符时行计数器递增 。
2.5 函数调用2.6 “悬挂”else
if(x == 0)if(y == 0) error();else{z = x + y;f(&z);}
这段代码的本意就不说了 , 这样写也是允许的 , 说说它的歧义 , C预言中 , else始终与同一对括号内最近的未匹配的if结合 , 它可不看;,所以显而易见:它没有按照本意集合第一个if , 所以还是那句话 , 请大哥{}套上 , 哪来这么多屁事
第3章:语义陷井 3.1数组与指针的切换表示
int dad[10][15];//父亲int (* son)[15];//定义一个儿子指针for (son = dad;son < &dad[10];son++)//找儿子{int *grandson;//定义一个孙子for(grandson = *son;grandson < &son[15];grandson++)//找孙子{//狂揍}}
3.2 非数组的指针
char *r;strcpy(r,s);strcat(r,t);
char *r , *malloc();r = malloc(strlen(s) + strlen(t) + 1);if(!r){complain();exit(1);}strcpy(r,s);strcat(r,t);/*一段时间后再使用*/free(r);
3.3 作为参数的数组声明3.4 地址传递并非值传递
char *p , *q;p = "xyz";//p实际上指向的是数组{'x','y','z','\0'}的首地址q = p; //首地址传递,p、q都指向数组了q[1] = 'Y';//都可操作数组空间p[2] = 'Z';
3.5 空指针并非空字符串3.6 边界计算与不对称边界3.7 整数溢出3.8 为main函数提供返回值第4章:连接 4.1 连接器
可能的空指针
在释放内存后使用了指向该内存的指针
赋值次序问题
拼写错误
被0除
失败的case语句(遗漏了break语句)
不可移植的代码(依赖了特定的机器实现)
宏参数没有使用圆括号
符号的丢失
异常的表达式
变量没有初始化
可疑的判断语句(例如,if(x=0))
/scanf的格式检查
这一看 , 这些现在的编译器都能检查出来啊 , 估计早就集成了lint , 这书太老了
4.2 声明与定义4.3 形参、实参、返回值
mian(){printf("%g\n",square(0.3));}double square(double x){return x*x;}
要么在main之前声明 ();,要么把定义放在main之前
如果我们需要在两个文件中分别定义main和 , 那么我们必须在调用它的文件中做声明