警告:吸烟有害健康;程序员:我不关心警告,只关心错误
ID:技术让梦想更伟大
作者:李肖遥
哇,功能终于都实现啦,告一段落了,好开心,,,
嗯?我看看你代码?,怎么还有这么多warnning?
啊?warnning怕什么呀,又没有错,赶紧提交吧,免得被催得头疼
那可不行,两个warnning就可能出现一个错误了
来,我通过编译选项将特定警告视为错误,你在编译试试?
嗯?what fuck,怎么还有几十个error了?
warnning只是不怎么明显的错误而已,要写出健壮的代码,这些还是要注意的。
好滴吧,我继续停留在修改bug的路上了。。。。。。
视warnning为无物是不是不知道bug怎么来的?
开发中经常会遇到由于各种原因导致的警告,虽然不影响具体的功能,没有出现错误,但是看起来总是让人厌烦,尤其是对于我这种有强迫症的开发者来说。
警告太多会影响对于真正问题的发掘,隐藏我们的视线。
凡是出现的警告都是有道理的,搞清楚它。
警告往往是因为会对内存调度等有潜在的威胁,大多数情况下不会出错,而一旦出错,就是灾难性的。
平时我们电脑蓝屏,或者手机卡死,大多数就是这样来的。
所以遇到警告,搞明白它,这是长功夫长能力的最好的时机
把warnning当作error是不是太狠了点?
警告也不一定是错误对吧,当确认它不会造成对运行结果有影响时,才可以去忽略。
有时,警告是因为写得不规范,改一种写法,对自己也是锻炼。
代码提交给测试部的时候,黑盒白盒测试也得过呀,对不对?
但是在开发过程中,不是所有的警告都需要去理会的,毕竟项目进度都摆在那里。
如果说明理由,或者是编译器的警告,暂且略过,没办法了。
warnning < ? < error
有没有哪些warnning确实是error,只是编译器没那么严格?或者有哪些warnning确实没啥事的,不需要花时间去查找了,这样岂不是提高效率?
比“忽略所有warning”要更安全,比开启“视所有warning为error”要宽松精准,所以下面就很关键了!
个人总结的应当视作error的warning
变量没有初始化就使用
函数调用完毕,无法保证用过的栈帧空间后续被如何使用(编译器是否开启优化、栈帧布局结构都有影响),侥幸是不行的。
把int指针和int相互赋值
虽说可以把指针的值(一个地址)当做一个int(其实是unsigned int)来理解,但考虑这种情况:int a=*p
被写成int a=p
而引发错误。
printf等语句中的格式串和实参类型不匹配
例如
printf("%s%d, szDebugString, ulGwId);
你的ulGwId是一个unsigned long型的,而你为它选择的输出形式却是 “%d”。
把unsigned int和int类型的两个变量比较
有符号数可能在比较之前被转换为无符号数而导致结果错误,这个就不多说了。
函数没有声明就使用
查看关于c编程的书籍可以知道,在函数调用之前,要求先声明,这是为了告诉编译器函数返回值的类型,函数接受的参数的类型和个数。
例如,函数没申明就会出现警告。自己去看结果吧
#include
int main(void)
{
int c;
c = sun();
printf("%d",c);
return 0;
}
int sun()
{
return 3;
}
指针类型不兼容
例如
#include
int main()
{
int array[3][4];
int **p = array;
}
那么我们改成这样就没问题了。
#include
int main()
{
int array[3][4];
//int **p = array;
int (*p)[4] = array;
}
函数应该有返回值但是没有return返回值
警告原因:出现这样的警告,有可能是你写了一个
unsigned long FuncA()
{
if()
{
return ulValue;
}
if()
{
return ulValue;
}
}
这样的函数,可能在两个if语句中,你都没有进入,这时,退出函数之前,你就根本没有值可以返回。所以要确保在任何情况下该函数都有一个返回值。
使用了影子变量(shadow variable)
内层作用域重新声明/定义了与外层作用域中同名的变量。举一个例子说明shadow变量的危害:
void set_value(int* val)
{
double r = 0.0;
if(isRandom) {
double r = this->generateRandomNumber();
}
*val = r;
}
上述代码运行后,val的值始终是0而不可能被改成随机值。
函数返回局部变量的地址
在C中,正常情况下,我们只能从函数中返回一个值。但在很多情况下,我们需要从函数中返回多个值,此时使用数组或指针能够很好地完成这样的任务。
这里是一个示例。这个程序使用一个整型数组作为参数,并将数组元素的和与积返回给调用函数。代码如下:
#include
#include
int* Pool(int array[],int size)
{
int *x;
int i=0;
int a[2]={0,1};
for(i=0;i {
a[0]+=array[i]; //存储数组元素值的和
a[1]*=array[i]; //存储数组元素值的积
}
//将数组的基地址赋值给整型指针
x=&a[0];
//返回整个数组
return x;
}
int main()
{
int a[]={1,2,3,4};
int *c; c = Pool(a,4);
printf("Sum = %d\nProduct = %d\n",c[0],c[1]);
getch();
return 0;
}
这样,使用数组和指针从C函数中返回多个值。在很多情况下你会发现这个技巧很有用,但是在C语言中绝不能返回函数内局部变量的地址。
在c语言中,一种典型的错误就是将一个指向局部变量的指针作为函数的返回值。
由于该数组是局部变量,因此在函数返回时其数组空间已经作废了,即指针应用一块无意义的地址空间,所以不会有返回值。
还有很多警告
其实还有很多,我这里不一一列举了,解不完的bug,数的尽的头发。欢迎留言补充!
最后
警告还是很重要的,说到底,我们干的就是要彻底去掉任何有损代码的威胁因素,这样才能写出健壮的代码,那么我们离职后,才能造福后人!
推荐阅读:
嵌入式编程专辑 Linux 学习专辑 C/C++编程专辑 关注微信公众号『技术让梦想更伟大』,后台回复“m”查看更多内容,回复“加群”加入技术交流群。 长按前往图中包含的公众号关注