对于 C 语言初学者而言,丢三落四的毛病比较严重,而某些错误,编译器也不会给出任何错误或警告的提示,以致于当程序编译通过而能运行时,浑然不知自己已经掉入了 C 的陷阱中。
注:本文如无特别说明,示范代码均在 Win7 64位英文系统, Dev-C++ 4.9 环境下编译执行。
#include<stdio.h> int main() { int a; printf("Input an integer: "); scanf("%d", a); /* 缺少取址符号 & */ printf("a = %d\r\n", a); return 0; }
示范代码能够编译通过且能“正常”运行,但是当输入一个整数时,会出现运行时错误而导致程序崩溃。
问题的关键在于 scanf 函数接收标准输入时,接收输入值的参数必须为某个地址。由于代码声明整型变量 a 且没有初始化,a 的值是随机的。当用户输入值后,会将值保存到变量 a 的值所在地址中,该值由于随机性,往往是非法的地址,所以导致程序发送运行时错误而崩溃。
#include<stdio.h> int main() { char a; printf("Please input a score rank from list (A, B, C, D): "); scanf("%c", &a); switch(a) { case 'A': printf("Excellent!\n"); break; case 'B': printf("Well Done!\n"); /* 缺少 break 语句?*/ case 'C': printf("Good!\n"); break; case 'D': printf("You should work hard!\n"); break; default: printf("Unknown rank: %c", a); } }
以上示范代码,当输入除 ”B“以外的字符时,都能按照原意运行。但是当输入”B“时,输出结果变成了如下所示:
Please input a score rank from list (A, B, C, D): B Well Done! Good!该问题就在于在判断 ‘B’ 的 case分支中,缺少了 break 语句,导致执行完该分支后,继续往下执行,直到在 ‘C’的case分支中遇到 break 语句才终止。该示范代码比较简单,估计不太容易犯这种低级错误。但是当case分支很多,而且每个分支的代码比较复杂时(分支太复杂,本身就是个坏的编程风格),就很容易丢掉 break 语句而导致执行逻辑错误了。
#include<string.h> #include<stdlib.h> #include<stdio.h> int main() { char *src_str = "Hello!"; int len = strlen(src_str); char *dst_str = (char*)malloc(len); printf("%d\n", len); if(dst_str) { //strcpy(dst_str, src_str); memcpy(dst_str, src_str, len); printf("%s\n", dst_str); free(dst_str); } return 0; }
6 Hello!?出错原因在于计算字符串长度时,忽略了字符串后面的 "\0"符号也占一个字符,上述代码,必须修改为 int len = strlen(src_str) + 1 才正确。
#include<stdio.h> int main() { int a[5], i; /* Initiate the array */ for(i = 0; i <= 5; i++) { a[i] = i; } /* Print the array */ for(i = 0; i <= 5; i++) { printf("%d\t", a[i]); } return 0; }
0 1 2 3 4 5
#include<stdio.h> int main() { int a[5]; int b = 100; int i; printf("b = %d\n", b); /* Initiate the array */ for(i = 0; i <= 5; i++) { a[i] = i; } /* Print the array */ for(i = 0; i <= 5; i++) { printf("%d\t", a[i]); } printf("\nb = %d", b); return 0; }输出结果如下:
b = 100 0 1 2 3 4 5 b = 5除了初始化变量 b 以外,我们只是对 b 进行打印操作,“理论上”应该不会改变它的值才对啊?!试想一下,如果是在某个复杂的算法函数中,在你毫无知觉的情况下,所使用的变量 b 已经被莫名其妙修改,你作何感想?现在能够理解我前面的话,不是危言耸听了吧?
编程是一件严肃细致的工作,程序员,尤其是 C 语言程序员,必须时刻保持严谨细致的作风,一丝不苟,才能减少错误的发生,避免一不小心掉入 C 语言的陷阱中,然后在茫茫代码中寻找那由于自己粗心大意而造成的低级错误。