1.词法陷阱
例1:if(x=y) break; 这就话的意思就是把y赋值x,判断x是否为0,实则是在判断y是否为0;
例2:while(c=' '|| c=='\t' || c=='\n')这句话的意思就是' '|| c=='\t' || c=='\n‘赋值给c,而有’ ‘符本身就是不为0的数,所以这就是while(1)的意思。
例3: int x=4,*p=new int ; *p=2; cout<<a/*p;这会编译器识别成/*注释符,正确的写法: int x=4,*p=new int ; *p=2; cout<<a/(*p);
这个涉及到编译器的编译过程,编译原理的问题:编译器是利用贪心算法来编译的,所以会识别成/*
例4:注意010和10 的区别010是八进制写法,一般也不会这样写。
例5: ’‘和“”的差别,’‘是单个字符,“”是字符串的表示。
2.语法陷阱
1.函数申明:
例子:(*(void(*)())0)();//这个函数申明
这个例子涉及函数指针和指针函数 ,看一下例子:float *a(),(*b)();这是两个定义呢,a是一个函数,返回值是一个float型指针,b是一个指针,返回值是float。这是因为()的优先级高于*的原因。
如何去调用一个指针函数呢,就是申明(*b)();也可以简化成b();
所以最初大那个例子可以解释了:
(void(*)())0=p是一个将常数0强制转化成返回值为void类型的函数指针p,那么就是(*p)()的意思,调用函数指针的意思。
2.运算符优先级:单目大于多目运算符,自左而右要高于自右向左。
这个需要记住的最重要的两点:1任何一个逻辑运算符的优先级低于任何一个关系运算符 2.移位运算符的优先级比算术运算符的要低,但比关系运算符要高。
3.结束标识符:
if(n<3) return //;(少了一个分号结束符)
i=3;
实际上就会变成if(n<3) return i=3;这样一句话。
4.函数调用:f()与f,f()是一个函数调用,f是一个函数地址
3.语义陷阱
1.看一段代码:
char *r,*malloc();
r=malloc(strlen(s)+strlen(t));
strcpy(r,s);
strcat(r,t);
这个是为r申请一段内存,但是忽略了申请不成功的情况。所以要修改考虑申请不成功的地方。
2.整数溢出:
如何判断两个数之和是否为整数溢出呢??结果是这样的,将int装换为unsigned int ,然后将这两个数相加判断是否超出了最后的整数。