C陷阱与缺陷笔记
我在Linux下编译的,具体是gcc某一个版本未知。
1、a---b -> a-- -b
2、y=x/*p; 这里不会当作z 除以*p,却会将/*当中注释的开始,并会一直寻找*/,为了表达意思最好这样:
y=x/ *p;或者:y=x/(*p);
3、r =hi<< 4 + low; 由于运算符优先级问题会先执行后面的加法再左移。所以必要的运算符优先级是需要记住的。
4、切忌悬挂else引起的问题:
if(x == 0)
If(y == 0 ) printf("");
else{
printf("");
}
这里的else会与紧靠前面的那个if相结合。
再次eg:
#defineassert(e) if(e)assert_error(__FILE__,__LINE__)
...
if(.....)
assert(...);
else
assert(...);
.......
当你展开之后你会觉得有的时候犯这样的错误很无语。所以调用的时候在if后面加括号或者不要写出这样的宏定义。当然最好不要这样写宏定义因为会有很多附带的bug。
5、C语言中只有四个运算符(&&,||,?:, ,)存在规定的求值顺序,&&,||运算符首先对左侧操作数求值,只在需要的时候才对右侧数据求值。 a?b:c运算符先求a,再求b,c。逗号运算符首先对左侧操作数求值并丢弃,在求右边的表达式。
6、数组的extern用法:
int a[10];
需要引用处可以这样:
extern int a[];
7、对文件读写的时候需要注意:对同一文件而言,一个输入操作不能随后直接紧跟一个输出操作,反之亦然。注意是对同一文件。要同时进行输入输出可以在中间调用fseek()就可以了。
8、千万不要写出这样的宏定义:
#define f (x) ((x)-1) //f 与(x)之间有空格;
这样会被理解为f 代表:(x)((x)-1)
还有一些注意的就是宏中每一个元素都尽量用()括起来,这样在宏替换的时候才不会出现你不想看到的结果。
9、在一定的条件下可以使用左移或者右移来代替乘法或者除法。而且移位运算会更快。但是切记:int n ;
n = .....;
n<<31;n<<0;这是合法的,而n<<32'n<<-1;这是非法的。
10、注意 == 与 = 的区别。
while(c == '\t'|| c =' ' || c == '\n') //这里将== 写成了= ;由于赋值运算符优先级最低,所以就成了(c == '\t' || c) =('' || c =='\n');这是一个非法的语句,(c== '\t' || c)不能作为左值,因为它的结果是一个常数,如果有的情况下左侧不是一个常数就不容易被检查出来了。
最好的在写的时候不要写错,同时也可以这样写:
while(\t' == c|| ' ' == c || \n' == c);这样如果不小心将==写成了=可以马上被检查出来。
11、很高效的二分查找法
int*bsearch(int* t,int n,int x)
{
int *lo = t,*hi = t+n; //lo始终保持为待查找区域的最起始元素,
//hi始终保持待查找区域最末元素的后一个元素(边界外了)
int *mid;
while(lo < hi){
mid = lo+(hi - lo)>>2;
if(x<*mid){
hi = mid;
}else if(x > *mid){
lo = mid +1;
}else{
return mid;
}
}
return NULL;
}