摘要:C語言是許多高校開設的第一門程序設計語言,使用方便靈活。根據C語言的特點,并結合實際教學,對在編程中經常遇到的錯誤進行分析、總結,為初學者盡快掌握C語言,提高程序設計水平提供借鑒。
關鍵詞:C語言;常見錯誤;邏輯錯誤;指針;變量
中圖分類號:TP312文獻標識碼:A文章編號:1009-3044(2009)26-7447-03
Common Errors in C Language
SHAN Shu-qian1, REN Jia-xun2
(1.North China Electric Power University Science Technology College, Baoding 071051, China; 2.BaoDing LiZhong Wheel Manufacturing CO.,LTD, Baoding 071051, China)
Abstract: C language is the first of many colleges and universities opened the door programming language, easy to use and flexible. According to C language features, combined with the practical teaching, often encountered in the programming errors in the analysis, summarization, as soon as possible for beginners to master c language, raise the level of program design to provide reference.
Key words: C language; common errors; logical errors; pointer; variable
C語言是國內外廣泛使用的一種計算機語言。由于其功能豐富、表達能力強、使用方便靈活、應用面廣、目標程序效率高、可移植性好等特點,深受廣大計算機工作者和應用人員的喜愛。許多高校都將其作為大一學生學習程序設計的入門語言。但C語言牽涉的概念比較復雜,規則多,雖然使用靈活,但是很容易出錯。結合實際教學中經驗,對學生學習C語言時常見錯誤進行歸納總結,供初學者借鑒。
1 C語言使用中常見的錯誤
1.1 大小寫錯誤
C語言規定所有的標識符是區分大小寫的;所有的關鍵字必須為小寫。如:sum與SUM就是不同的標識符。
1.2 用戶自定義標識符的中錯誤
在C語言中規定,用戶自定義的標識符可以用來區分變量、符號常量、函數名、數組、類型等數據對象,只能由數字、字母、下劃線組成且第一個字符必須是字母或者下劃線。用戶自定義的標識符不能與關鍵字相同。許多學生在使用過程中經常忘記這一規定。如定義一個整型變量:int char;錯誤之處在于將關鍵字char 定義為用戶標識符,這是不允許的。
1.3 使用未定義的變量或者變量使用前未賦值
main( ){ int a,b=3;printf(“a=%d,b=%d,c=%d\”,a,b,c);}
此例中,會得到如下的錯誤提示:error C2065: 'c' : undeclared identifier執行 cl.exe 時出錯。出錯原因在于變量c在使用前未定義。
定義變量c之后的程序如下:
main( ){ int a,b=3,c=4;printf(“a=%d,b=%d,c=%d\”,a,b,c);}
程序運行時并沒出現語法錯誤,運行結果為:a=-858993460,b=3,c=4
從本例可以看出,在定義變量a,b,c的同時,僅完成了對變量b、c的初始化,變量a在使用之前未被賦值,因而得到a=-858993460的結果。此結果的得出是由分配給變量a的內存空間里的數據經轉化得到。這個數值是隨機值,由分配給a的內存空間里的數值決定。此類錯誤為邏輯錯誤,不易察覺。程序可以修改為:
main( ){ int a=2,b=3,c=4;printf(“a=%d,b=%d,c=%d\”,a,b,c);}
運行結果為:a=2,b=3,c=4
1.4 混淆“=”與“==”
在C語言中,“=”是賦值運算符,表示將“=”右邊的值賦給左端的變量,不能做等號使用。“==”才是表示兩個數據是否相等的關系運算符。“==”的優先級比“=”高。
例如:
main(){ int a=0,b=1;if (a=b)printf(“a=%d”,a); }
輸出結果:a=1
分析:執行if語句時,無論a原來為何值,都被b的值所取代,a值變為1。所以表達式“a=b”的結果永遠為非零,if 語句執行,輸出結果a=1。
要表示a與b比較的關系,則程序改為:
main(){ int a=0,b=1;if (a==b)printf(“a=%d”,a);}
只有當a和b的值相等時,if語句才執行,輸出a的值;否則,if語句結束。
1.5 使用邏輯運算符常出現的錯誤
邏輯表達式求解時,并非所有的邏輯運算符都被執行,只是在必須執行下一個邏輯運算符才能求出表達式的解時,才執行該運算符。有以下的程序段:
int a=1,b=2,c=3,d=4,m=1,n=1; 執行完語句“ (m=a>b)(n=c>d);”后,m和n的值分別為 0和 1。a>b的結果為0,因而m的值變為0。運算符“”的第一個運算對象為0(即為假),所以不管右端的表達式(n=c>d)的值為何,邏輯與的結果都為0。因而(n=c>d)是不必運算的,所以n保持原值1,而不是0。
同理:int a=1,b=2,c=3,d=4,m=1,n=1; 執行完語句“ (m=ad);”后,m和n的值分別為1和 1,n保持原值不變。
1.6 對復合語句忘記加花括號“{ }”
有以下程序段:
int i=1,sum =0;
while(i<=10)
sum=sum+i;
i++;
程序本意是要執行1+2+...+10,但while語句卻是一個死循環。原因是循環語句中的循環體應是由花括號“{}”括起來的一個復合語句。由于在while語句中循環體少了花括號,則循環體僅由一個語句構成,即sum=sum+i;而語句i+ +;則是循環語句的下一條語句,不再是循環體中的語句。由于起循環控制作用的變量i的值始終未被改變,因此構成死循環。根據題意,應將該程序段中的while語句修改為以下形式:
int i=1,sum =0;
while(i<=10)
{ sum=sum+i;
i++;
}
1.7 用scanf()函數輸入變量值時的錯誤
1.7.1 漏寫取地址運算符“”
如:int a; scanf(“%d”,a); /* a前漏寫 */
C語言中,scanf()函數的輸入項必須用地址表示,作用是按照a在內存的地址將輸入的數值存入。
1.7.2 輸入普通字符也應輸入
例如有程序段:int a; scanf(“a=%d”,a);從鍵盤輸入數值,使a為10。則正確的輸入形式應該為:a=10《回車》
如果忘記輸入普通字符“a=”,變量a將不會得到正確數值10。
1.8 忽略某些函數的求值順序
如:main ( )
{intx=100;
printf (“ %d,%d,%d,%d”, x++,x,--x,x);
}
運行結果為:99,99,99,100
這是由于在Turbo c中執行printf()函數時,參數是按照從右到左的順序被壓入棧中的,即先壓入x,在壓入—x,然后x,最后是x++。彈出時依次為:x++,x,--x,x。因而得到上述結果。
1.9 switch語句中缺少break語句
例:int day;scanf(“%d”,day);
switch (day)
{case 1 : printf(“Monday”);
case 2 : printf(“Tuesday”);
case 3 : printf(“Wednesday”);
default: printf(“input error!\”);
}
程序本意是根據變量day的取值(1,2或3),分別打印出Monday,Tuesday,Wednesday否則打印input error。
如果輸入day的值為1,打印結果是MondayTuesdayWednesdayinput error而不是我們想象中的Monday。導致此結果原因在于:在執行第一個printf()函數調用語句之后,程序繼續執行接下來的三個printf()函數調用語句。這種情況的產生是由于在switch語句中缺少break語句所造成。將上述程序段改為以下形式:
int day;scanf(“%d”,day);
switch (day)
{case 1 : printf(“Monday”);break;
case 2 : printf(“Tuesday”); break;
case 3 : printf(“Wednesday”);break;
default: printf(“input error!\”);
}
1.10 使用數組時,數組下標越界
有以下程序:
void main()
{int i,a[10];
for (i=0; i<=10;i++)
a[i]=i;
}
程序的本意是將數組a中的十個元素分別賦值為0,1,…,9。但是卻把比較部分寫成了“i<=10”,數組元素從a[0]開始,a[10]這個元素是不存在的。正確的形式為:
void main()
{int i,a[10];
for (i=0; i<10;i++)
a[i]=i;
}
1.11 混淆字符和字符串的表示形式
如:char ch=“A”;是錯誤的。 ‘A’ 和“A”是完全不同的常量,‘A’是字符常量,在內存中占一個字節,它可以賦值給字符變量;而“A”是字符串常量,它包括兩個字符:‘A’和‘\\0’,在內存中占二個字節。無法存放在字符變量中,C語言沒有字符串變量,使用字符型數組來存放和處理字符串。如:char c[10]=“welcome”;
1.12 使用未初始化的指針
指針變量是C語言中的一個特殊類型的變量,用于存放變量的地址。指針變量定義后應確定其指向。在沒有確定指針的具體指向前,指針變量的內容是隨機的地址,盲目地引用將十分危險。例如:下列程序用于比較兩個數的大小,并在主函數中由小到大輸出結果。
swap(int *pl,int *p2)
{ int *p; *p=*pl; *pl=*p2; *p2=*p;}
main()
{ int a,b; int *pa,*pb;
scanf(“%d,%d”,a,b);
pa=a;pb=b;
if(a>b)swap(pa,pb);
printf(“%d,%d”,a,b);}
swap函數的功能是以*P為中間變量,實現指針pl,p2所指單元內容互換。P只是定義卻沒有具體指向。當swap函數被調用時,系統僅給指針p分配一個內存單元,而這一內存里存放的地址未定。它可能是操作系統或其它用戶區的某一內存地址,當運行程序時,很可能使不屬于本程序的某個內存內容被修改,從而造成整個系統的崩潰。swap函數正確的形式為:
swap(int *pl,int *p2)
{ int p; p=*pl; *pl=*p2; *p2=p;}
1.13 指針變量所指向的變量類型與其定義的類型不符
定義指針變量的一般格式為:類型說明符 *指針變量名;其中“類型說明符”規定的是指針變量所指向的變量的類型。C語言規定一個指針變量只能指向同一類型的變量。如:
main()
{ float f;int *p:
p=f;}
f類型是單精度實型的,而指針p是指向整型變量的指針,f與*p數據類型不符。不符合C語言的語法。應該為:float *p;
1.14 在數組使用指針變量時的常見錯誤
程序如下:
main( ){ int a[10];int b[3][4];int *c[10];int(*d)[5];int *p;}
1) a為一維數組名,有類似一級指針的性質,a為數組中首元素a[0]的地址,*a為int型數據。
2) b為二維數組名,有類似二級指針的性質,*b為元素b[0][0]的地址(即b[0]),**b為int型數據。
3) c為一維數組名,有類似一級指針的性質,且又是指針數組,故c有類似二級指針性質,*c為地址,**c為int型數據。
4) d是一個指向含有5個整型數據的一維數組的指針變量,故d有類似二級指針的性質,*d為地址,**d為int型數據。
按照上述解釋,若有語句“p=b;”則是錯誤的。雖然p是int型指針,二維數組b也是int型,但p是一級指針,而b是一個二維數組,是二級指針,編譯時系統報錯。正確的寫法是:p=b[0]。
2 結束語
上述列舉的一些錯誤,是初學者在編程中經常遇到的錯誤。當然在學習中還會碰到其它一些不容忽視的錯誤,需具體情況具體分析并認真總結。只有這樣才能消除這些常見錯誤,提高編程水平。
參考文獻:
[1] 譚浩強.C程序設計[M].3版.北京:清華大學出版社,2005.
[2] 陳友明.C語言使用中常見錯誤分析[J]. 電腦知識與技術,2006(1).
[3] 牛雅莉,趙芳林.C語言中常見邏輯錯誤分析[J].北京工業職業技術學院學報,2008,7(2).