分类: C/C++
2007-08-05 23:03:33
C traps & pitfalls 学习笔记
1,正确和错误的形式比较
Error |
Ok |
原因 |
char *slash=’/’; |
char *slash=”/”; |
‘/’并非字符串 |
a = b /*p; |
a = b/(*p); |
贪婪原则,/*被认为是注释 |
if(flags & FLAG != 0) … |
if( (flags & FLAG) != 0) .. |
!=优先级比&高 |
r = hi<<4 + low |
r = (hi<< 4) + low |
+法优先级高于移位 |
r = hi<<4 + low |
r = hi<< 4 | low |
移位优先级高于逻辑运算 |
while(c=getc(in)!=EOF) 。。 |
while((c=getc(in))!=EOF).. |
赋值运算低于其他 |
if(x[i] >big); big = x[i]; |
if(x[i]>big) big = x[i]; |
注意分号易错 |
|
|
|
2,形式分析
函数声明(*(void(*)())0)();的分析
只需要把声明中的变量名和声明末尾的分号去掉,然后再将剩余的部分用一个括号“封装其起来”就能够得到该类型的类型转换符。
声明float (*h)(); à 类型转换符(float(*)()) :指向返回值为浮点类型的函数的指针
并且:调用表达式 (*fp)() 在ANSI C标准中可以简写为fp() 这只是一种简写。
(*0)();à必须添加类型转换 (*(void (*)())0)(); 得出是对地址为0的函数指针进行调用
typedef 可以很好的解决这个问题:typedef void (*funcptr)();就声明了funcptr这个新的类型,上式可以简化为(*(funcptr)0)();
优先级比较
除[],函数调用,成员操作符号以外,单目操作符最高(类型转换也是单目),单目运算是自右而左,*p++为*(p++),要注意。比单目低的接下来是双目操作符,其中,算术运算符最高,移位次之,然后是关系运算,接着是逻辑运算,赋值运算,最后是条件运算(三目)。
1) 任何一个逻辑运算符的优先级低于任何一二关系运算符
2) 移位运算符优先级比算术运算符低,但是比关系运算符要高
3) 6个关系运算符关系运算符不一样,==和!=比其他低
4) 逻辑运算符都不相同:按位运算比顺序运算优先级高:与& > 异或^ > 或|,顺序与&& > 顺序或||
5) 赋值运算符优先级从右至左
例如:tax = income>4000 && res<5 ? 3.5:2.0;等同于
tax = ((income>4000) && (res<5)) ? 3.5:2.0;
int (*ap)[31];表明*ap是一个31个int的数组,则ap是指向这么一个数组的指针
对字符串的连接,注意分配字符串长度需要加1,例如
r = malloc(strlen(s)+strlen(t) +1);
if(!r) exit(1);
strcpy(r,s);strcat(r,t);
C语言中为了避免命名冲突,
采用了static限制可见度在本源文件内,static int a;static int g(int x)
char filename[7]=”passwd”;extern char filename[]; //OK
或者
char *filename=”passwd”;extern char *filename。//OK
注意不能忽视#define中的空格;
宏并不是函数,只是替换;注意括号预防优先级错误;宏也不是类型定义
除法运算时的截断,这个要十分注意
C语言的数组初始化列表中中允许出现多余的逗号例如
int days[] = { 31,31,31,30,29,
30,31,30,30,29, };
以0开头的数是8进制数,10和010是不一样的
优先级:& 优先级低于 != ;
<<优先级低于 +;
malloc:malloc返回void*类型,需要强制转换成自己的类型
malloc分配有可能会失败,需要检测是否为NULL
注意scanf需要加&符号:
例如: int a;
scanf(“%d”,&a);
printf(“%d\n”,a);
处理栈的top问题:一个栈的栈顶TOP变量就是指还未使用的空内存区
输入输出格式化:
%d有符号整数%u无符号整数%o八进制
%x小写十六进制%X大写十六进制%s字符串
%c字符%e科学计数法形式输出浮点数