最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Recommended C Style and Coding Standards中文翻譯版第2/3頁

 更新時間:2014年04月28日 11:45:23   作者:  
本文翻譯自Recommended C Style and Coding Standards(C語言編碼風(fēng)格和標(biāo)準(zhǔn)),需要的朋友可以參考下

6. 空格

復(fù)制代碼 代碼如下:
int i;main(){for(;i["]<i;++i){--i;}"];read('-'-'-',i+++"hell\
o, world!\n",'/'/'/'));}read(j,i,p){write(j/p+p,i---j,i/i);}

- 不光彩的事情,模糊C代碼大賽,1984年。作者要求匿名。
通常情況下,請使用縱向和橫向的空白??s進和空格應(yīng)該反映代碼的塊結(jié)構(gòu)。例如,在一個函數(shù)定義與下一個函數(shù)的注釋之間,至少應(yīng)該有兩行空白。

如果一個條件分支語句過長,那就應(yīng)該將它拆分成若干單獨的行。

復(fù)制代碼 代碼如下:

    if (foo->next==NULL && totalcount<needed && needed<=MAX_ALLOT
        && server_active(current_input)) { ...

也許下面這樣更好
復(fù)制代碼 代碼如下:

    if (foo->next == NULL
        && totalcount < needed && needed <= MAX_ALLOT
        && server_active(current_input))
    {
        ...

類似地,復(fù)雜的循環(huán)條件也應(yīng)該被拆分為不同行。
復(fù)制代碼 代碼如下:

    for (curr = *listp, trail = listp;
        curr != NULL;
        trail = &(curr->next), curr = curr->next )
    {
        ...

其他復(fù)雜的表達式,尤其是那些使用了?:操作符的表達式,最好也能拆分成多行。
復(fù)制代碼 代碼如下:

    c = (a == b)
        ? d + f(a)
        : f(b) - d;

當(dāng)關(guān)鍵字后面有放在括號內(nèi)的表達式時,應(yīng)該使用空格將關(guān)鍵字與左括號分隔(sizeof操作符是個例外)。在參數(shù)列表中,我們也應(yīng)該使用空格顯式 的將各個參數(shù)隔開。然而,帶有參數(shù)的宏定義一定不能在名字與左括號間插入空格,否則C預(yù)編譯器將無法識別后面的參數(shù)列表。

7. 例子

復(fù)制代碼 代碼如下:
/*
         * Determine if the sky is blue by checking that it isn't night.
         * CAVEAT: Only sometimes right.  May return TRUE when the answer
         * is FALSE.  Consider clouds, eclipses, short days.
         * NOTE: Uses 'hour' from 'hightime.c'.  Returns 'int' for
         * compatibility with the old version.
         */
                int                             /* true or false */
        skyblue()
        {
                extern int      hour;           /* current hour of the day */

                return (hour >= MORNING && hour <= EVENING);
        }

        /*
         * Find the last element in the linked list
         * pointed to by nodep and return a pointer to it.
         * Return NULL if there is no last element.
         */
                node_t *
        tail(nodep)
                node_t  *nodep;                 /* pointer to head of list */
        {
                register node_t *np;            /* advances to NULL */
                register node_t *lp;            /* follows one behind np */

                if (nodep == NULL)
                        return (NULL);
                for (np = lp = nodep; np != NULL; lp = np, np = np->next)
                        ;       /* VOID */
                return (lp);
        }

8. 簡單語句

每行只應(yīng)該有一條語句,除非多條語句關(guān)聯(lián)特別緊密。

復(fù)制代碼 代碼如下:

    case FOO:  oogle (zork);  boogle (zork);  break;
    case BAR:  oogle (bork);  boogle (zork);  break;
    case BAZ:  oogle (gork);  boogle (bork);  break;

for或while循環(huán)語句的空體應(yīng)該單獨放在一行并加上注釋,這樣可以清晰的看出空體是有意而為,并非遺漏代碼。
復(fù)制代碼 代碼如下:

    while (*dest++ = *src++)
        ;    /* VOID */

不要對非零表達式進行默認測試,例如:
復(fù)制代碼 代碼如下:

    if (f() != FAIL)

比下面的代碼更好
復(fù)制代碼 代碼如下:

    if (f())

即使FAIL的值可能為0(在C中0被認為是假)。當(dāng)后續(xù)有人決定使用-1替代0作為失敗返回值時,一個顯式的測試將解決你的問題。即使比較的值永遠不會改變,我們也應(yīng)該使用顯式的比較;例如
復(fù)制代碼 代碼如下:

if (!(bufsize % sizeof(int)))

應(yīng)該被寫成

復(fù)制代碼 代碼如下:

if ((bufsize % sizeof(int)) == 0)

這樣可以反映這個測試的數(shù)值(非布爾)本質(zhì)。一個常見的錯誤點是使用strcmp測試字符串是否相同,這個測試的結(jié)果永遠不應(yīng)該被放棄。比較好的方法是定義一個宏STREQ。

復(fù)制代碼 代碼如下:

    #define STREQ(a, b) (strcmp((a), (b)) == 0)

對謂詞或滿足下面約束的表達式,非零測試經(jīng)常被放棄:

0表示假,其他都為真。
通過其命名可以看出返回真是顯而易見的。
用isvalid或valid稱呼一個謂詞,不要用checkvalid。

一個非常常見的實踐就是在一個全局頭文件中聲明一個布爾類型"bool"。這個特殊的名字可以極大地提高代碼可讀性。

復(fù)制代碼 代碼如下:

    typedef int    bool;
    #define FALSE    0
    #define TRUE    1


復(fù)制代碼 代碼如下:

    typedef enum { NO=0, YES } bool;

即便有了這些聲明,也不要檢查一個布爾值與1(TRUE,YES等)的相當(dāng)性;可用測試與0(FALSE,NO等)的不等性替代。絕大多數(shù)函數(shù)都可以保證為假的時候返回0,但為真的時候只返回非零。
復(fù)制代碼 代碼如下:

    if (func() == TRUE) { ...

必須被寫成
復(fù)制代碼 代碼如下:

    if (func() != FALSE) { ...

如果可能的話,最好為函數(shù)/變量重命名或者重寫這個表達式,這樣就可以顯而易見的知道其含義,而無需再與true或false比較了(例如,重命名為isvalid())。

嵌入賦值語句也有用武之地。在一些結(jié)構(gòu)中,在沒有降低代碼可讀性的前提下,沒有比這更好的方式來實現(xiàn)這個結(jié)果了。

復(fù)制代碼 代碼如下:

    while ((c = getchar()) != EOF) {
        process the character
    }

++和--操作符可算作是賦值語句。這樣,為了某些意圖,實現(xiàn)帶有副作用的功能。使用嵌入賦值語句也可能提高運行時的性能。不過,大家應(yīng)該在提高的性能與下降的可維護性之間做好權(quán)衡。當(dāng)在一些人為的地方使用嵌入賦值語句時,這種情況會發(fā)生,例如:
復(fù)制代碼 代碼如下:

    a = b + c;
    d = a + r;

不應(yīng)該被下面代碼替代:
復(fù)制代碼 代碼如下:

    d = (a = b + c) + r;

即使后者可能節(jié)省一個計算周期。在長期運行時,由于優(yōu)化器漸獲成熟,兩者的運行時間差距將下降,而兩者在維護性方面的差異將提高,因為人類的記憶會隨著時間的流逝而衰退。

在任何結(jié)構(gòu)良好的代碼中,goto語句都應(yīng)該保守地使用。使用goto帶來好處最大的地方是從switch、for和while多層嵌套中跳出,但這樣做的需求也暗示了代碼的內(nèi)層結(jié)構(gòu)應(yīng)該被抽取出來放到一個單獨的返回值為成功或失敗的函數(shù)中。

復(fù)制代碼 代碼如下:

        for (...) {
            while (...) {
                ...
                if (disaster)
                    goto error;

            }
        }
        ...
    error:
        clean up the mess

當(dāng)需要goto時候,其對應(yīng)的標(biāo)簽應(yīng)該被放在單獨一行,并且后續(xù)的代碼縮進一級。使用goto語句時應(yīng)該增加注釋(可能放在代碼塊的頭)以說明它的功用和目的。continue應(yīng)該保守地使用,并且盡可能靠近循環(huán)的頂部。Break的麻煩比較少。

非原型函數(shù)的參數(shù)有時需要被顯式做類型提升。例如,如果函數(shù)期望一個32bit的長整型,但卻被傳入一個16bit的整型數(shù),可能會導(dǎo)致函數(shù)棧不對齊。指針,整型和浮點值都會發(fā)生此問題。


9. 復(fù)合語句

復(fù)合語句是一個由括號括起來的語句列表。有許多種常見的括號格式化方式。如果你有一個本地標(biāo)準(zhǔn),那請你與本地標(biāo)準(zhǔn)保持一致,或選擇一個標(biāo)準(zhǔn),并持續(xù)地使用它。在編輯別人的代碼時,始終使用那些代碼中使用的樣式。

復(fù)制代碼 代碼如下:

control {
        statement;
        statement;
}

上面的風(fēng)格被稱為"K&R風(fēng)格",如果你還沒有找到一個自己喜歡的風(fēng)格,那么可以優(yōu)先考慮這個風(fēng)格。在K&R風(fēng)格中,if-else語句中的else部分以及do-while語句中的while部分應(yīng)該與結(jié)尾大括號在同一行中。而其他大部分風(fēng)格中,大括號都是單獨占據(jù)一行的。

當(dāng)一個代碼塊擁有多個標(biāo)簽時,每個標(biāo)簽應(yīng)該單獨放在一行上。必須為C語言的switch語句的fall-through特性(即在代碼段與下一個case語句之前間沒有break)增加注釋以利于后期更好的維護。最好是lint風(fēng)格的注釋/指示。

復(fù)制代碼 代碼如下:

switch (expr) {
case ABC:
case DEF:
    statement;
    break;
case UVW:
    statement;
    /*FALLTHROUGH*/
case XYZ:
    statement;
    break;
}

這里,最后那個break是不必要的,但卻是必須的,因為如果后續(xù)另外一個case添加到最后一個case的后面時,它將阻止fall-through錯誤的發(fā)生。如果使用default case,那么應(yīng)該該default case放在最后,且不需要break,如果它是最后一個case。

一旦一個if-else語句在if或else段中包含一個復(fù)合語句,if和else兩個段都應(yīng)該用括號括上(稱為全括號(fully bracketed)語法)。

復(fù)制代碼 代碼如下:

if (expr) {
    statement;
} else {
    statement;
    statement;
}

在如下面那樣的沒有第二個else的if-if-else語句序列里,括號也是不必可少的。如果ex1后面的括號被省略,編譯器解析將出錯:
復(fù)制代碼 代碼如下:

if (ex1) {
    if (ex2) {
        funca();
    }
} else {
    funcb();
}

一個帶else if的if-else語句在書寫上應(yīng)該讓else條件左對齊。
復(fù)制代碼 代碼如下:

if (STREQ (reply, "yes")) {
    statements for yes
    ...
} else if (STREQ (reply, "no")) {
    ...
} else if (STREQ (reply, "maybe")) {
    ...
} else {
    statements for default
    ...
}

這種格式看起來像一個通用的switch語句,并且縮進反映了在這些候選語句間的精確切換,而不是嵌套的語句。

Do-while循環(huán)總是使用括號將循環(huán)體括上。

下面的代碼非常危險:

復(fù)制代碼 代碼如下:

#ifdef CIRCUIT
#    define CLOSE_CIRCUIT(circno)    { close_circ(circno); }
#else
#    define CLOSE_CIRCUIT(circno)
#endif

    ...
    if (expr)
        statement;
    else
        CLOSE_CIRCUIT(x)
    ++i;


注意,在CIRCUIT沒有定義的系統(tǒng)上,語句++i僅僅在expr是假的時候獲得執(zhí)行。這個例子指出宏用大寫命名的價值,以及讓代碼完全括號化的價值。

有些時候,通過break,continue,goto或return,if可以無條件地進行控制轉(zhuǎn)移。else應(yīng)該是隱式的,并且代碼不應(yīng)該縮進。

復(fù)制代碼 代碼如下:

if (level > limit)
    return (OVERFLOW)
normal();
return (level);

平坦的縮進告訴讀者布爾測試在密封塊的其他部分是保持不變的。

10. 操作符

一元操作符不應(yīng)該與其唯一的操作數(shù)分開。通常,所有其他二元操作符都應(yīng)該使用空白與其操作樹分隔開,但'.'和'->'例外。當(dāng)遇到復(fù)雜表達式的時候我們需要做出一些判斷。如果內(nèi)層操作符沒有使用空白分隔而外層使用了,那么表達式也許會更清晰些。

如果你認為一個表達式很難于閱讀,可以考慮將這個表達式拆分為多行。在接近中斷點的最低優(yōu)先級操作符處拆分是最好的選擇。由于C具有一些想不到的優(yōu)先級規(guī)則,混合使用操作符的表達式應(yīng)該使用括號括上。但是過多的括號也會使得代碼可讀性變差,因為人類不擅長做括號匹配。

二元逗號操作符也會被使用到,但通常我們應(yīng)該避免使用它。逗號操作符的最大用途是提供多元初始化或操作,比如在for循環(huán)語句中。復(fù)雜表達式,例如那些使用了嵌套三元?:操作符的表達式,可能引起困惑,并且應(yīng)該盡可能的避免使用。三元操作符和逗號操作符在一些使用宏的地方很有用,諸如getchar。在三元操作符?:前的邏輯表達式的操作數(shù)應(yīng)該被括起來,并且兩個子表達式的返回值應(yīng)該是相同類型。

11. 命名約定

毫無疑問,每個獨立的工程都有一套自己的命名約定,不過仍然有一些通用的規(guī)則值得參考。

1).為系統(tǒng)用途保留以下劃線開頭或下劃線結(jié)尾的名字,并且這些名字不應(yīng)該被用在任何用戶自定義的名字中。大多數(shù)系統(tǒng)使用這些名字用于用戶不應(yīng) 該也不需知道的名字中。如果你一定要使用你自己私有的標(biāo)識符,可以用標(biāo)識它們歸屬的包的字母作為開頭。
2).#define定義的常量名字應(yīng)該全部大寫。
3).Enum常量應(yīng)該大寫或全部大寫。
4).函數(shù)名、typedef名,變量名以及結(jié)構(gòu)體、聯(lián)合體與枚舉標(biāo)志的名字應(yīng)該用小寫字母。
5).很多"宏函數(shù)"都是全部大寫的。一些宏(諸如getchar和putchar)使用小寫字母命名,這事因為他們可能被當(dāng)成函數(shù)使用。只有在宏的行為類似一 個函數(shù)調(diào)用時才允許小寫命名的宏,也就是說它們只對其參數(shù)進行一次求值,并且不會給具名形式參數(shù)賦值。有些時候我們無法編寫出一個具有函數(shù)行為的 宏,即使其參數(shù)也只是求值一次。
6).避免在同一情形下使用不同命名方式,比如foo和Foo。同樣避免foobar和foo_bar這種方式。需要考慮這樣所帶來的困惑。
7).同樣,避免使用看起來相似的名字。在很多終端以及打印設(shè)備上,'I'、'1'和'l'非常相似。給變量命名為l特別糟糕,因為它看起來十分像常量'1'。
通常,全局名字(包括enum)應(yīng)該具有一個統(tǒng)一的前綴,通過該前綴名我們可以識別出這個名字歸屬于哪個模塊。全局變量可以選擇匯集在一個全局結(jié) 構(gòu)中。typedef的名字通常在結(jié)尾加一個't'。

避免名字與各種標(biāo)準(zhǔn)庫中的名字沖突。一些系統(tǒng)可能包含一些你所不需要的庫。另外你的程序?qū)砟程旌芸赡芤惨獢U展。

12. 常量

數(shù)值型常量不應(yīng)該被硬編碼到源文件中。應(yīng)該使用C預(yù)處理器的#define特性為常量賦予一個有意義的名字。符號化的常量可以讓代碼具有更好的可讀性。在一處地方統(tǒng)一定義這些值也便于進行大型程序的管理,這樣常量值可以在一個地方進行統(tǒng)一修改,只需修改define的值即可。枚舉數(shù)據(jù)類型更適合聲明一組具有離散值的變量,并且編譯器還可以對其進行額外的類型檢查。至少,任何硬編碼的值常量必須具有一段注釋,以說明該值的來歷。

常量的定義應(yīng)該與其使用是一致的;例如使用540.0作為一個浮點數(shù),而不是使用540外加一個隱式的float類型轉(zhuǎn)換。有些時候常量0和1被直接使用而沒有用define進行定義。例如,一個for循環(huán)語句中用于標(biāo)識數(shù)組下標(biāo)的常量,

復(fù)制代碼 代碼如下:

for (i = 0; i < ARYBOUND; i++)

上面代碼是合理的,但下面代碼
復(fù)制代碼 代碼如下:

door_t *front_door = opens(door[i], 7);
if (front_door == 0)
    error("can't open %s\\\\n", door[i]);

是不合理的。在最后的那個例子中,front_door是一個指針。當(dāng)一個值是指針的時候,它應(yīng)該與NULL比較而不是與0比較。NULL被定義在標(biāo)準(zhǔn)I/O庫頭文件stdio.h中,在一些新系統(tǒng)中它在stdlib.h中定義。即使像1或0這樣的簡單值,我們最好也用define定義成TRUE和FALSE定義后再使用(有些時候,使用YES和NO可讀性更好)。

簡單字符常量應(yīng)該被定義成字面值,不應(yīng)該使用數(shù)字。不鼓勵使用非可見文本字符,因為它們是不可移植的。如果非可見文本字符十分必要,尤其是當(dāng)它們在字符串中使用時,它們應(yīng)該定義成三個八進制數(shù)字的轉(zhuǎn)義字符(例如: '\007‘)而非一個字符。即使這樣,這種用法也應(yīng)該考慮其機器相關(guān)性,并按這里的方法處理。

13. 宏

復(fù)雜表達式可能會被用作宏參數(shù),這可能會因操作符優(yōu)先級順序而引發(fā)問題,除非宏定義中所有參數(shù)出現(xiàn)的位置都用括號括上了。對這種因參數(shù)內(nèi)副作用而引發(fā)的問題,我們似乎也無能為例,除了在編寫表達式時杜絕副作用(無論如何,這都是一個很好的主意)。如果可能的話,盡量在宏定義中對宏參數(shù)只進行一次求值。有很多時候我們無法寫出一個可像函數(shù)一樣使用的宏。

一些宏也當(dāng)成函數(shù)使用(例如,getc和fgetc)。這些宏會被用于實現(xiàn)其他函數(shù),這樣一旦宏自身發(fā)生變化,使用該宏的函數(shù)也會受到影響。在交換宏和函數(shù)時務(wù)必要小心,因為函數(shù)參數(shù)是按值傳遞的,而宏參數(shù)則是通過名稱替換。只有在宏定義時特別謹慎小心,才有可能減少使用宏時的擔(dān)心。

宏定義中應(yīng)該避免使用全局變量,因為全局變量的名字很可能被局部聲明遮蓋。對于那些對具名參數(shù)進行修改(不是這些參數(shù)所指向的存儲區(qū)域)或被用作賦值語句左值的宏,我們應(yīng)該添加相應(yīng)的注釋以給予提醒。那些不帶參數(shù)但引用變量,或過長或作為函數(shù)別名的宏應(yīng)該使用空參數(shù)列表,例如:

復(fù)制代碼 代碼如下:

#define    OFF_A()    (a_global+OFFSET)
#define    BORK()    (zork())
#define    SP3()    if (b) { int x; av = f (&x); bv += x; }

宏節(jié)省了函數(shù)調(diào)用和返回的額外開銷,但當(dāng)一個宏過長時,函數(shù)調(diào)用和返回的額外開銷就變得微不足道了,這種情況下我們應(yīng)該使用函數(shù)。

在一些情況下,讓編譯器確保宏在使用時應(yīng)該以分號結(jié)尾是很有必要的。

復(fù)制代碼 代碼如下:

if (x==3)
    SP3();
else
    BORK();

如果省略SP3調(diào)用后面的分號,后面的else將會匹配到SP3宏中的那個if。有了分號,else分支就不會與任何if匹配。SP3宏可以這樣安全地實現(xiàn):
復(fù)制代碼 代碼如下:

#define SP3() \\\\
    do { if (b) { int x; av = f (&x); bv += x; }} while (0)

手工給宏定以加上do-while包圍看起來很別扭,而且很多編譯器和工具會抱怨在while條件是一個常量值。一個用來聲明語句的宏可以使得編碼更加容易:
復(fù)制代碼 代碼如下:

#ifdef lint
    static int ZERO;
#else
#    define ZERO 0
#endif
#define STMT( stuff )        do { stuff } while (ZERO)

我們可以用下面代碼來聲明SP3宏:
復(fù)制代碼 代碼如下:

#define SP3() \\\\
    STMT( if (b) { int x; av = f (&x); bv += x; } )

使用STMT宏可以有效阻止一些可以潛在改變程序行為的打印排版錯誤。

除了類型轉(zhuǎn)換、sizeof以及上面那些技巧和手法,只有當(dāng)整個宏用括號括上時才應(yīng)該包含關(guān)鍵字。

14. 條件編譯

條件編譯在處理機器依賴、調(diào)試以及編譯階段設(shè)定特定選項時十分有用。不過要小心條件編譯。各種控制很容易以一種無法預(yù)料的方式結(jié)合在一起。如果使用#ifdef判斷機器依賴,請確保當(dāng)沒有機器類型適配時,返回一個錯誤,而不是使用默認機器類型(使用#error并縮進一級,這樣它可以一些老舊的編譯器下工作)。如果你#ifdef優(yōu)化選項,默認情況下應(yīng)該是一個未經(jīng)優(yōu)化的代碼,而不是一個不兼容的程序。確保測試的是未經(jīng)優(yōu)化的代碼。

注意在#ifdef區(qū)域內(nèi)的文本可能會被編譯器掃描(處理),即使#ifdef求值的結(jié)果為假。但即使文件的#ifdef部分永遠不能被編譯到(例如,#ifdef COMMENT),這部分也不該隨意的放置文本。

盡可能地將#ifdefs放在頭文件中,而不是源文件中。使用#ifdef定義可以在源碼中統(tǒng)一使用的宏。例如,一個用于檢查內(nèi)存分配的頭文件可能這樣實現(xiàn):(省略了REALLOC和FREE):

復(fù)制代碼 代碼如下:

    #ifdef DEBUG
        extern void *mm_malloc();
    #    define MALLOC(size) (mm_malloc(size))
    #else
        extern void *malloc();
    #    define MALLOC(size) (malloc(size))
    #endif

條件編譯通常應(yīng)該基于一個接一個的特性的。多數(shù)情況下,都應(yīng)該避免使用機器或操作系統(tǒng)依賴。
復(fù)制代碼 代碼如下:

    #ifdef BSD4
        long t = time ((long *)NULL);
    #endif

上面代碼之所以糟糕有兩個原因:很可能在某個4BSD系統(tǒng)上有更好的選擇,并且也可能存在在某個非4BSD系統(tǒng)中上述代碼是最佳代碼。我們可以通過定義諸如TIME_LONG和TIME_STRUCTD等宏作為替代,并且在諸如config.h的配置文件中定義一個合適的宏。


15. 調(diào)試

"C代碼。C代碼運行。運行,代碼,運行... 請運行!!!" -- Barbara Tongue

如果你使用枚舉,第一個枚舉常量應(yīng)該是一個非零值,或者第一個常量應(yīng)該指示一個錯誤。

復(fù)制代碼 代碼如下:

enum { STATE_ERR, STATE_START, STATE_NORMAL, STATE_END } state_t;
enum { VAL_NEW=1, VAL_NORMAL, VAL_DYING, VAL_DEAD } value_t;

未初始化的值后續(xù)將會自己獲取。

檢查所有錯誤返回值,即使是那些"不能"失敗的函數(shù)的返回值??紤]即使之前所有的文件操作都已經(jīng)成功了,close()和fclose也可能失敗。編寫你自己的函數(shù),使得它們以一種明確的方式測試錯誤、返回錯誤碼或從程序中退出。包含大量調(diào)試和錯誤檢查代碼,并把其中大多數(shù)留在最終的產(chǎn)品中。甚至檢查那些"不可能"的錯誤。

使用assert機制保證傳給每個函數(shù)的值都是定義明確的,并且中間結(jié)果是形式良好的。

盡可能少的在調(diào)試代碼中使用#ifdef。例如,如果mm_malloc是一個調(diào)試用的內(nèi)存分配器,那么MALLOC將挑選合適的分配器,避免使用#ifdef在代碼中堆砌垃圾,并且使得分配之間的差異變得清晰,只是在調(diào)試期會分配些額外內(nèi)存。

復(fù)制代碼 代碼如下:

#ifdef DEBUG
#    define MALLOC(size)  (mm_malloc(size))
#else
#    define MALLOC(size)  (malloc(size))
#endif

對那些"不可能"溢出的對象做邊界校驗。一個向變長存儲區(qū)寫入的函數(shù)應(yīng)該接受一個參數(shù)maxsize,該參數(shù)即目標(biāo)內(nèi)存區(qū)域的大小。如果有時候目標(biāo)內(nèi)存區(qū)域大小未知,一些maxsize的"魔數(shù)"值應(yīng)該意味著"沒有邊界檢查"。當(dāng)邊界檢查失敗,請確保這個函數(shù)做一些有用的事情,諸如退出程序或返回一個錯誤狀態(tài)。
復(fù)制代碼 代碼如下:

/*
 * INPUT: A null-terminated source string `src' to copy from and
 * a `dest' string to copy to.  `maxsize' is the size of `dest'
 * or UINT_MAX if the size is not known.  `src' and `dest' must
 * both be shorter than UINT_MAX, and `src' must be no longer than
 * `dest'.
 * OUTPUT: The address of `dest' or NULL if the copy fails.
 * `dest' is modified even when the copy fails.
 */
    char *
copy (dest, maxsize, src)
    char *dest, *src;
    unsigned maxsize;
{
    char *dp = dest;

    while (maxsize\-\- > 0)
        if ((*dp++ = *src++) == '\\\\0')
            return (dest);

    return (NULL);
}


總之,記住一個程序產(chǎn)生錯誤答案的速度快兩倍(譯注:是否有南轅北轍的意味),實則是變得無限緩慢,這個道理對那些偶爾崩潰或打擊有效數(shù)據(jù)的程序同樣成立。


相關(guān)文章

  • 一文詳解如何實現(xiàn)QT的多語言切換(靜態(tài)+動態(tài))

    一文詳解如何實現(xiàn)QT的多語言切換(靜態(tài)+動態(tài))

    這篇文章主要給大家介紹了關(guān)于如何實現(xiàn)QT的多語言切換(靜態(tài)+動態(tài))的相關(guān)資料,Qt是一款跨平臺的C++應(yīng)用程序開發(fā)框架,提供了一套豐富的工具和類庫來簡化應(yīng)用程序開發(fā),文中通過代碼介紹的非常詳細,需要的朋友可以參考下
    2024-06-06
  • 深入二叉樹兩個結(jié)點的最低共同父結(jié)點的詳解

    深入二叉樹兩個結(jié)點的最低共同父結(jié)點的詳解

    本篇文章是對二叉樹兩個結(jié)點的最低共同父結(jié)點進行了詳細的分析介紹,需要的朋友參考下
    2013-05-05
  • 詳解C++11 變參模板

    詳解C++11 變參模板

    這篇文章主要介紹了C++11 變參模板的相關(guān)資料,幫助大家更好的理解和學(xué)習(xí)c++11,感興趣的朋友可以了解下
    2020-08-08
  • 一起來學(xué)習(xí)C++的函數(shù)指針和函數(shù)對象

    一起來學(xué)習(xí)C++的函數(shù)指針和函數(shù)對象

    這篇文章主要為大家詳細介紹了C++函數(shù)指針和函數(shù)對象,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2022-03-03
  • Qt寫入Json文件的方法詳解(含源碼+注釋)

    Qt寫入Json文件的方法詳解(含源碼+注釋)

    在Qt庫中,為JSON的相關(guān)操作提供了完整的類支持,下面這篇文章主要給大家介紹了關(guān)于Qt寫入Json文件(含源碼+注釋)的相關(guān)資料,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下
    2022-10-10
  • C語言順序表實現(xiàn)代碼排錯

    C語言順序表實現(xiàn)代碼排錯

    這篇文章主要介紹了C語言順序表實現(xiàn)方法,大家參考使用吧
    2013-12-12
  • C/C++中宏/Macro的深入講解

    C/C++中宏/Macro的深入講解

    這篇文章主要給大家介紹了關(guān)于C/C++中宏/Macro的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家學(xué)習(xí)或者使用C/C++具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-06-06
  • 淺談VS中添加頭文件時顯示無法找到文件的問題

    淺談VS中添加頭文件時顯示無法找到文件的問題

    下面小編就為大家?guī)硪黄獪\談VS中添加頭文件時顯示無法找到文件的問題。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-01-01
  • C語言線索二叉樹基礎(chǔ)解讀

    C語言線索二叉樹基礎(chǔ)解讀

    線索二叉樹還是按照鏈二叉樹的方法創(chuàng)建,只不過在結(jié)點原本為空的左指針改為指向該結(jié)點在中序遍歷中的前驅(qū),結(jié)點原本為空的右指針改為指向該結(jié)點在中序遍歷中的后繼,也就是說把空的指針給利用了起來
    2022-04-04
  • C++鏈表倒序?qū)崿F(xiàn)方法

    C++鏈表倒序?qū)崿F(xiàn)方法

    這篇文章主要介紹了C++鏈表倒序?qū)崿F(xiàn)方法,是一個很經(jīng)典的C++鏈表操作實例,需要的朋友可以參考下
    2014-08-08

最新評論

临潭县| 东兰县| 开化县| 雅安市| 汪清县| 潞西市| 仁化县| 佛山市| 兴文县| 三台县| 丰原市| 临潭县| 绵竹市| 察隅县| 华池县| 和林格尔县| 石楼县| 朔州市| 栾城县| 桑日县| 鲁山县| 绥滨县| 中超| 庆安县| 连云港市| 突泉县| 富平县| 龙泉市| 军事| 正宁县| 浦江县| 如东县| 永善县| 金华市| 淳化县| 静安区| 兴业县| 泽普县| 大冶市| 南投市| 辽宁省|