C语言常见的程序错误
1、丢失分号
每个C语句都必须以分号结尾。丢失分号可能引起编译器的混淆,导致“丢失”错误消息。请看下面语句:
a = x + y
b = m/n;
编译器将把第二行作为第一行的一部分,把b看作是一个变量。因而得到在第二行的“未定义变量名”错误消息。注意,消息和位置都是不正确的。在这种情况下,所报告的行没有错误,就应检查前一行是否丢失了分号。还有就是当丢失分号时,可能导致编译器“疯狂”运行,产生一系列的错误消息。如果发现这种可疑错误,在错误列表的开始处检查是否丢失了分号。
2、误用分号
请看下面代码:
for ( i = 1; i <= 10; i ++ );
sum = sum + i;
该代码用于把1-10的所有整数加起来。但实际结果是只有i的最后“退出”值加到了sum上。这种错误的其他一些情况有:
(1)while ( x < max );
{
....
}
(2)if ( T >= 2000 );
grade = 'A';单个分号表示的是空语句,因此语法上是合法的。编译器不会产生任何错误消息。可见,这种错误比语法错误更糟糕。
该用 == 而误用 =
当要执行一个关系测试时,很可能忘了使用双等号。例如:
if ( code = 1)
count ++;
这句语句在语法上是合法的。变量code被赋值1,然后,因为code = 1为真,因而count递增。实际上,上面代码不会对code做任何关系测试。不论code的值如何,总是会运行count ++语句。
在其他控制语句(如for和while)中,可能发生类似的错误。在循环控制语句中的这种错误可能会导致无限循环。
3、丢失括号
在编写深度嵌套的循环时,往往会忘了加闭括号。这往往能被编译器检测到,因为开括号的数目应与闭括号的匹配。但是,如果把匹配的括号放在了错误的地方,编译器不能发现这种错误,程序将产生不可预知的结果。
括号的另一个严重的问题是,当多个语句要组合在一起时,没有使用括号。例如,请看以下语句:
for ( i = 1; i <= 10; i ++)
sum1 = sum1 + i;
sum2 = sum2 + i*i;
printf("%d %d",sum1,sum2);
上面代码本意是计算从1 - 10、步长为1的sum1和sum2,然后显示其值。但实际上for循环只是把第一个语句作为其循环体,即:
sum1 = sum1 + i;
因此,语句
sum2 = sum2 + i*i;
只是在循环退出时计算了一次。这个代码段的正确编写方法是如下添加括号:
for ( i = 1; i <= 10; i ++)
{
sum1 = sum1 + i;
sum2 = sum2 + i*i;
}
printf("%d %d",sum1,sum2);
如果只有一个括号,那结果将是不可预知的。
4、丢失引号
每个字符串都必须用双引号扩起来,而单个字符常量则用单引号。如果遗漏了引号,那么字符串或者字符将被当作一个变量。例如:
if ( response == YES)
Grade = A;
这里YES和A都被看作为变量,因此会出现“为定义变量名”的错误消息。
5、误用引号
只要处理单个字符,就可能使用单引号。应小心确保有关的变量已经正确声明了。例如,如果city已经声明为char类型变量,那么下面语句
city = 'M';
是不合法的。
6、使用不正确的注释字符
每个注释都应以开注释符/*为开始,以闭注释符*/为结尾。这两种之间的所有内容都被编译器忽略。如果遗漏了闭注释符*/,那么编译器将往程序后面查询,把所有行都看作为注释。如果找不到闭注释符*/,则得到一个错误消息。请看以下代码:
.....
/* comment line 1
statement1;
statement2;
/* comment line 3*/
statement 3;
......
由于在第一个注释行漏了闭注释符*/,那么其后的所有语句,知道第二个注释行的闭注释符*/,都被忽略掉。记住,C语言不支持嵌套注释。假设想把以下代码段注释掉:
...
x = a - b;
y = c - d;
/* compute ratio */
ratio = x/y;
...
如果试图如下这样添加注释符是不正确的。
/* x = a - b;
y = c - d;
/* compute ratio */
ratio = x/y; */
第一个开注释符与第一个闭注释符匹配,因此这两个注释符之间的行将被忽略,而语句
ratio = x/y;
没有注释掉。要给这段代码添加注释的正确方法是:
/*x = a - b;
y = c - d; */
/* compute ratio */
/* ratio = x/y; */
7、未定义变量
C语言要求每个变量在使用之前都应声明为某种类型。在开发大型程序时,很可能使用一个临时变量来保存中间结果,但忘了声明它。
8、忽略了运算符的优先级
表达式是根据运算符的优先级来计算的。建议没有记清优先级的朋友们先温习以下优先级的相关知识。请看以下语句:
if(value = product() >= 100)
tax = 0.05 * value;
函数调用product()返回两个数的乘积,该乘积再与100作比较,如果大于或者等于100,则关系测试为真,从而把1赋值给了value;否则把0赋值给了value。无论是那种情况,value的值只能为1或者0。这不是我们想要的结果。我们希望的是把由product()返回的值赋值给value,然后再与100作比较。如果value的值大于或者等于100,那么就应用如下语句来计算tax:
tax = 0.05 * value;
产生这种错误的原因是关系运算符的优先级比赋值运算符的优先级更高。可以用如下括号来强制进行赋值运算。
if((value = product()) >= 100)
tax = 0.05 * value;
同样,逻辑运算符&&和||的优先级比算术运算符和关系运算符的优先级更低,而在这两者中,&&的优先级又比||的更高。看以下语句的区别:
(1)if (p > 50 || c > 50 && m > 60 && t > 180)
x = 1;
(2)if ((p > 50 || c > 50) && m > 60 && t > 180)
x = 1;
(3)if ((p > 50 || c > 50 && m > 60 )&& t > 180)
x = 1;
9、忽略了递增递减运算符的计算顺序
我们经常在循环语句中使用递增和递减运算符。例如:
.....
i = 0;
while ( (c = getchar()) != '\n'))
string[i++] = c;
}
string[i - 1] = c;
语句string[i++] = c 等价于
string[i] = c;
i = i + 1;
它与语句string[++i] = c 是不同的,该语句等价于
i = i + 1;
string[i] = c;
10、在函数调用中实参和形参类型不匹配
当调用带参数的函数时,应确保传递的值的类型,与被调用函数所期望的类型相匹配。否则,可能出现错误。如果有必要,在局部使用类型转换运算符。例如:
a、y = cos((double) x);
b、__TextOut(hDC, CHARGING_IN_X, CHARGING_IN_Y, (_WORD*)g_ChargingStrTab[0],-1);
发表于 @ 2007年01月03日 21:28:00|评论(loading...)|编辑