K&R C風格函數 C–K&R C 與 ANSI C的區別

    前些天在看getopt源碼, 一種前所未見的函數定義方法html

 1 int
 2 getopt(nargc, nargv, ostr)
 3     int nargc;
 4     char * const nargv[];
 5     const char *ostr;
 6 {
 7     static char *__progname = 0;
 8     static char *place = EMSG;        /* option letter processing */
 9     char *oli;                /* option letter list index */
10         __progname = __progname?__progname:_progname(*nargv);
11 
12     _DIAGASSERT(nargv != NULL);
13     _DIAGASSERT(ostr != NULL);
14 
15     if (optreset || !*place) {        /* update scanning pointer */
16         optreset = 0;
17         if (optind >= nargc || *(place = nargv[optind]) != '-') {
18             place = EMSG;
19             return (-1);
20         }
21         if (place[1] && *++place == '-'    /* found "--" */
22             && place[1] == '\0') {
23             ++optind;
24             place = EMSG;
25             return (-1);
26         }
27     }                    /* option letter okay? */
28     if ((optopt = (int)*place++) == (int)':' ||
29         !(oli = strchr(ostr, optopt))) {
30         /*
31          * if the user didn't specify '-' as an option,
32          * assume it means -1.
33          */
34         if (optopt == (int)'-')
35             return (-1);
36         if (!*place)
37             ++optind;
38         if (opterr && *ostr != ':')
39             (void)fprintf(stderr,
40                 "%s: illegal option -- %c\n", __progname, optopt);
41         return (BADCH);
42     }
43     if (*++oli != ':') {            /* don't need argument */
44         optarg = NULL;
45         if (!*place)
46             ++optind;
47     }
48     else {                    /* need an argument */
49         if (*place)            /* no white space */
50             optarg = place;
51         else if (nargc <= ++optind) {    /* no arg */
52             place = EMSG;
53             if (*ostr == ':')
54                 return (BADARG);
55             if (opterr)
56                 (void)fprintf(stderr,
57                     "%s: option requires an argument -- %c\n",
58                     __progname, optopt);
59             return (BADCH);
60         }
61          else                /* white space */
62             optarg = nargv[optind];
63         place = EMSG;
64         ++optind;
65     }
66     return (optopt);            /* dump back option letter */
67 }

還覺得是什麼新穎的寫法, 原來是C最原始的寫法K&R C風格, 而咱們如今寫的都是ANSI C風格, 原諒我讀書少, 沒有認真讀過那些C 的經典書籍數組

ANSI C 對 K&R C 的修訂

(本段根據《C Programming Language》和C語言標準整理。不求完整,但願列出最多見的差別)

  • 對於源文件內部的標識符,有效的最小長度擴充到31個字符。文件間鏈接時,標識符的最小有效長度仍然爲6個字符。(許多實現都支持更大的長度)
  • 增長了幾個新關鍵字:void,const,volatile,signed,enum。拋棄了老關鍵字entry。
  • 在換意字符 \ 以後寫非規定的序列,其做用肯定爲無定義。
  • 規定8和9都不是八進制數的合法字符。
  • 引進了數的後綴字符:整數的U和L,浮點數的F和L。
  • 規定連續出現的字符串常量將被拼接在一塊兒。
  • 引進了「寬字符」的概念。
  • 將字符也肯定爲帶符號(signed)和不帶符號(unsigned)的。
  • 丟棄了long float(原來做爲double的同義詞)。
  • 引入了void類型,用 (void*) 表示通用指針的類型(過去人們一般用 (char*))。
  • 對算術類型規定了最小表示範圍。要求每一個C語言系統用頭文件(<limits.h>;和<float.h>;)說明實現中的具體規定。
  • 引進了枚舉定義enum。
  • 採用了來自C++的類型修飾符,如const。
  • 規定字符串常量是不可修改的。
  • 改變了算術類型的隱含轉換規則。
  • 刪去了一些過期賦值運算符,如 =+。規定賦值運算符都是基本單詞,如 += 之間不能有空格分隔。
  • 引進了與一元 - 運算符對應的一元 + 運算符。
  • 指向函數的指針能夠直接放在函數調用的位置,沒必要顯式地寫間接操做。
  • 容許結構地總體賦值,做爲函數參數和返回值傳遞。
  • 容許將取地址運算符做用於數組,獲得的是指向有關數組的指針。
  • 標準規定 sizeof 運算符的返回值爲 size_t 類型(某個無符號整型),這一類型在標準頭文件<stddef.h>;裏定義。同時在那裏定義的還有 ptrdiff_t 類型,它是指針減運算的結果類型。
  • 規定取地址運算符不能做用於 register 變量。
  • 規定移位表達式的類型爲其左運算對象的類型。
  • 容許創建指向過數組末元素一個位置的指針,以及對它的算術運算和關係運算。
  • (從C++)引進了包含參數類型的函數原型概念,引進了變長參數表函數的概念。仍容許老的形式,但僅僅是做爲過期形式保留。
  • 標準規定任何局部聲明的做用域僅僅是當前的塊(複合語句)。
  • 規定函數參數做爲加入函數體(複合語句)的聲明,所以不能用變量聲明去覆蓋。
  • 有關名字空間的規定:全部結構、聯合和枚舉標記在一個名字空間裏,標號是另外一個名字空間。
  • 聯合變量在定義時也能夠初始化,規定初始化其第一個成分。
  • 自動結構、聯合和數組也能夠初始化,但限制其初始化方式(其中只能包含常量表達式)。
  • 帶大小描述的字符數組也能夠用大小與之相同的字符串常量初始化(結束的 \0 被刪除)。
  • 開關語句的控制表達式和case標號能夠是任何整型的(包括字符類型)。

 

參考:函數

        ANSI和K&R兩種函數定義風格post

        C–K&R C 與 ANSI C的區別ui

相關文章
相關標籤/搜索