天天看點

C陷阱與缺陷代碼分析之第0章導讀

作者:劉昊昱 

部落格:http://blog.csdn.net/liuhaoyutz

陷阱一:

先來看第一個例子,因為它在原書第二頁,我們将它命名為page2.c,代碼如下:

1#include <stdio.h>
2
3main()
4{
5    printf("Hello World!");
6}
           

編譯執行過程如下:

C陷阱與缺陷代碼分析之第0章導讀

這個程式有兩個問題:

一、因為列印語句後面沒加換行符,是以指令提示符直接出現在列印語句”Hello World!”後面。這個從執行結果可以很明顯的看出來。

二、main函數和其它任何函數一樣,如果沒有顯式的聲明傳回值類型,那麼函數傳回值類型預設就是int型。但是在page2.c程式中,并沒有給出任何傳回值。

通常這不會造成什麼危害,如果沒有給出傳回值,實際上會預設傳回某個随機整數,隻要該數值不被用到,就無關緊要。但是在某些情況下,main函數的傳回值卻很重要,因為大多數C語言實作都是通過main函數的傳回值告訴作業系統該程式的執行是成功還是失敗。典型的處理方案是,傳回0,表示程式執行成功,傳回其它值,表示程式執行失敗。這樣,如果一個程式的main函數并不傳回任何值,那麼即使該程式執行成功,也有可能看上去是執行失敗。如果正在使用一個軟體管理系統,該系統關注程式執行成功還是失敗,那麼很可能得到令人驚訝的結果。

上面的程式正确的寫法page2-ok.c代碼如下:

1#include <stdio.h>
2
3main()
4{
5    printf("Hello World!\n");
6    return 0;
7}
           

陷阱二:

下面來看第二個例子,因為它在原書的第二和第三兩頁,是以我們将它命名為page2_3.c,其代碼如下:

1#include <stdio.h>
 2
 3int main()
 4{
 5    int i, a[10];
 6    for(i = 0; i <= 10; i++)
 7        a[i] = 0;
 8
 9    return 0;
10}
           

這段代碼本意是初始化包含10個元素的數組a的所有元素為0,但是for循環中,循環條件本來應該寫為i < 10,但是程式卻寫為i <= 10,是以在循環到第11次時(此時i的值為10),實際上并不存在的a[10]被設定為0,也就是記憶體中在數組a之後的一個字(word)的記憶體被設定為0。如果編譯這個程式的編譯器是按照記憶體位址遞減的方式來給變量配置設定記憶體,那麼記憶體中數組a之後的一個字實際上是配置設定給了整型變量i,例如先給i配置設定的位址是1000,按照位址遞減的原則,給a[9]配置設定的記憶體就是998。這樣在第11次循環中,i被設定為0,這樣一來,for循環就變成了一個死循環。

程式的正确寫法page2_3-ok.c代碼如下:

1#include <stdio.h>
 2
 3int main()
 4{
 5    int i, a[10];
 6    for(i = 0; i < 10; i++)
 7        a[i] = 0;
 8
 9    return 0;
10}