我们来自五湖四海,不为别的,只因有共同的爱好,为中国互联网发展出一分力!

C编程常见问题总结

2014年07月03日17:37 阅读: 32908 次

标签: C编程常见问题总结

1.忘记注释结束符
代码
?
a = b; /* 出现bug
c = d; /* c = d将不会执行*/
2.意外的赋值/意外的bool表达式
代码:
?
if(a = b) c; ?/*a恒等于b,只有当b!=0的时候才执行*/
再看下面的代码:
?
if(0 < a < 5) c; ? /*布尔表达式恒为真*/
上面代码中的bool表达式恒为真,由于0 < a的值为0或1,永远都小于5成立,当然C中没有bool表达式,这里只是假设
?
3.有缺陷的宏
代码:
?
#define assign(a,b) a=(char)b
assign(x,y>>8)
变成
?
x=(char)y>>8 ? ?/* 可能不是你的目的 */?
4.不匹配的头文件
代码:
?
//foo.h:
struct foo { BOOL a};
//F1.c
#define BOOL char
#include "foo.h"
//F2.c
#define BOOL int
#include "foo.h"
F1与F2对结构体foo中的BOOL类型定义不一致,如果交互就会出现错误
?
5.飘忽不定的返回值
可能你会写下面的代码:
?
int foo (a)
{ if (a) return(1); } /* bug,因为有时候没有值返回 */
6.不可预知的结构体
看下面的比特包结构:
?
struct eeh_type
{
? ? uint16 size: ? ? ? ? ?10; ? /* 10 bits */
? ? uint16 code: ? ? ? ? ? 6; ? /* 6 bits */
};
取决于用哪个C编译器,还有你的机器使用大小端,这段代码实现为:
?
<10-bits><6-bits> 或 <6-bits><10-bits>
?
同时取决于C编译器、机器体系结构、不可思议的优先设置,这些项可能对齐到最近的8, 16, 32, or 64 bits.
?
7.不确定的求值顺序
? foo(pointer->member, pointer = &buffer[0]);
不同的编译器针对函数参数有不同的求值顺序,gcc是从左到右的求值顺序,有的编译器是从右往左
?
8.容易改变的块作用域
代码:
?
if( ... )?
? ? ? foo();?
? else?
? ? ? bar();
当加上调试输出信息:
?
if( ... )?
? ? foo(); ? ? ? ? ?
else?
? ? printf( "Calling bar()" ); ? ? ?/* 注意! else止于此 */
? ? bar(); ? ? ? ? ? ? ? ? ? ? ? ? ?/* 注意! bar永远会被执行 */
9.不安全的返回值
代码:
?
char *f() {?
? ?char result[80];?
? ?sprintf(result,"anything will do");?
? ?return(result); ? ?/* 注意! result 被分配在栈上. */?
?}
?
int g()?
{?
? ?char *p;?
? ?p = f();?
? ?printf("f() returns: %s\n",p);?
}?
10.未定义副作用(side effects)
哪怕一个简单的表达式,C没有定义副作用的顺序,结果取决于你的编译器,i/i++可能等于0或1,看下面的代码:
?
#include
int foo(int n) {printf("Foo got %d\n", n); return(0);}
int bar(int n) {printf("Bar got %d\n", n); return(0);}
int main(int argc, char *argv[])?
{
? ? int m = 0;
? ? int (*(fun_array[3]))();
? ? int i = 1;
? ? int ii = i/++i;
? ? printf("i/++i = %d, ",ii);
? ? fun_array[1] = foo; fun_array[2] = bar;
? ? (fun_array[++m])(++m); ? ??
? ? return 0;
}
11.未初始化的局部变量
事实上这个bug不是那么出名,但是一旦发生严重性不会输给其他的bug,看下面的代码:
?
void foo(a)
{ int b;
? if(b) {/* bug! b没有被初始化 */ }
}
现代编译器会发出错误的警告,看下面代码:
?
void foo(int a)?
{ BYTE *B;
? ?if(a) B=Malloc(a);
? ? ? ? ? if(B) { /* BUG! B 可能没被初始化 */ *b=a; }?
}
12.杂乱的编译时环境
编译时环境产生成百上千的编译信息,我们对此知之甚少。有些危险的常用名,导致很难被发现:
?
#include
#define BUFFSIZE 2048?
long foo[BUFSIZ]; ? //注意拼写: BUFSIZ != BUFFSIZE
编译器不会报错,因为BUFSIZ已经在stdio.h中定义
?
13.八进制数
在C中,八进制数以0开始,如果数字中没有‘8’或‘9’出现,编译器不会警告
?
?int numbers[] = { 001, ? ? ? ?
? ? ? ? ? ? ? ? ? ? ? ? ? ?010, ? ? ? ?// 8 而不是 10?
? ? ? ? ? ? ? ? ? ? ? ? ? ?014 ?}; ? ? // 12, 而不是 14?
14.有符号字符
C中的有符号char可能出现各种错误,比如128是一个负数,另外,任何使用低精度整数都必须十分的小心,C使得这些太容易被忽略了
?
char s = 127;
unsigned char u = 127;
s++; ? ? ?/* 结果是负数 */
if (s
if(s>127) { /* 永不可能为true */ ?}
if(u<0) { ?/* 永不可能为true*/ ?}
15.糟糕的“标准库”
代码:
?
{ int a=1,b=2;
? char buf[10];
? scanf("%d %d",a,b); ? ? ? ? ? ?// &a,&b??
? sprintf(buf,"this is the result: %d %d"); // 溢出 ? ? ? ? ? ?
}
分享到: 更多
?2019 安全焦点 版权所有.