第1章 聲明和初始化
      基本類型
      1.1 我該如何決定使用哪種整數類型?
      1.2 為什麼不精確定義標準類型的大小?
      1.3 因為C語言沒有精確定義類型的大小,所以我一般都用typedef定義int16和int32。然後根據實際的機器環境把它們定義為int、short、long等類型。這樣看來,所有的問題都解決了,是嗎?
      1.4 新的64位機上的64位類型是什麼樣的?
      指針聲明
      1.5 這樣的聲明有什麼問題?char *p1, p2;我在使用p2的時候報錯了。
      1.6 我想聲明一個指針,並為它分配一些空間,但卻不行。這樣的代碼有什麼問題?char *p;*p=malloc(10);
      聲明風格
      1.7 怎樣聲明和定義全局變量和函數最好?
      1.8 如何在C中實現不透明(抽象)數據類型?
      1.9 如何生成“半全局變量”,就是那種只能被部分源文件中的部分函數訪問的變量?
      存儲類型
      1.10 同一個靜態(static)函數或變量的所有聲明都必須包含static存儲類型嗎?
      1.11 extern在函數聲明中是什麼意思?
      1.12 關鍵字auto到底有什麼用途?
      類型定義(typedef)
      1.13 對于用戶定義類型,typedef 和#define有什麼區別?
      1.14 我似乎不能成功定義一個鏈表。我試過typedef struct{char *item;NODEPTR next;}* NODEPTR;但是編譯器報了錯誤信息。難道在C語言中結構不能包含指向自己的指針嗎?
      1.15 如何定義一對相互引用的結構?
      1.16 Struct{ } x1;和typedef struct{ } x2;這兩個聲明有什麼區別?
      1.17 “typedef int(*funcptr)();”是什麼意思?
      const 限定詞
      1.18 我有這樣一組聲明︰typedef char *charp;const charp p;為什麼是p而不是它指向的字符為const?
      1.19 為什麼不能像下面這樣在初始式和數組維度值中使用const值?const int n=5;int a[n];
      1.20 const char *p、char const *p和char *const p有什麼區別?
      復雜的聲明
      1.21 怎樣建立和理解非常復雜的聲明?例如定義一個包含N個指向返回指向字符的指針的函數的指針的數組?
      1.22 如何聲明返回指向同類型函數的指針的函數?我在設計一個狀態機,用函數表示每種狀態,每個函數都會返回一個指向下一個狀態的函數的指針。可我找不到任何方法來聲明這樣的函數——感覺我需要一個返回指針的函數,返回的指針指向的又是返回指針的函數,如此往復,以至無窮。
      數組大小
      1.23 能否聲明和傳入數組大小一致的局部數組,或者由其他參數指定大小的參數數組?
      1.24 我在一個文件中定義了一個extern數組,然後在另一個文件中使用,為什麼sizeof取不到數組的大小?
      聲明問題
      1.25 函數只定義了一次,調用了一次,但編譯器提示非法重聲明了。
      1.26 main的正確定義是什麼?void main正確嗎?
      1.27 我的編譯器總在報函數原型不匹配的錯誤,可我覺得沒什麼問題。這是為什麼?
      1.28 文件中的第一個聲明就報出奇怪的語法錯誤,可我看沒什麼問題。這是為什麼?
      1.29 為什麼我的編譯器不允許我定義大數組,如double array[256][256]?
      命名空間
      1.30 如何判斷哪些標識符可以使用,哪些被保留了?
      初始化
      1.31 對于沒有顯式初始化的變量的初始值可以作怎樣的假定?如果一個全局變量初始值為“零”,它可否作為空指針或浮點零?
      1.32 下面的代碼為什麼不能編譯? intf(){char a[]=\〃Hello, world!\〃;}
      1.33 下面的初始化有什麼問題?編譯器提示“invalid initializers ”或其他信息。char *p=malloc(10);
      1.34 char a[]= \〃string literal\〃;和char *p=\〃string literal\〃;初始化有什麼區別?當我向p[i] 賦值的時候,我的程序崩潰了。
      1.35 char a{[3]}= \〃abc\〃;是否合法?
      1.36 我總算弄清楚函數指針的聲明方法了,但怎樣才能初始化呢?
      1.37 能夠初始化聯合嗎?
      第2章 結構、聯合和枚舉
      結構聲明
      2.1 struct x1{ };和typedef struct{ }x2;有什麼不同?
      2.2 這樣的代碼為什麼不對?struct x{ };x thestruct;
      2.3 結構可以包含指向自己的指針嗎?
      2.4 在C語言中用什麼方法實現抽象數據類型最好?
      2.5 在C語言中是否有模擬繼承等面向對象程序設計特性的好方法?
      2.6 為什麼聲明extern f(struct x *p);給我報了一個晦澀難懂的警告信息?
      2.7 我遇到這樣聲明結構的代碼︰struct name {int namelen;char namestr[1];};然後又使用一些內存分配技巧使namestr數組用起來好像有多個元素,namelen記錄了元素個數。它是怎樣工作的?這樣是合法的和可移植的嗎?
      2.8 我听說結構可以賦給變量也可以對函數傳入和傳出。為什麼K&R1卻明確說明不能這樣做?
      2.9 為什麼不能用內建的==和!=操作符比較結構?
      2.10 結構傳遞和返回是如何實現的?
      2.11 如何向接受結構參數的函數傳入常量值?怎樣創建無名的中間的常量結構值?
      2.12 怎樣從/向數據文件讀/寫結構?
      結構填充
      2.13 為什麼我的編譯器在結構中留下了空洞?這導致空間浪費而且無法與外部數據文件進行“二進制”讀寫。能否關掉填充,或者控制結構域的對齊方式?
      2.14 為什麼sizeof返回的值大于結構大小的期望值,是不是尾部有填充?
      2.15 如何確定域在結構中的字節偏移量?
      2.16 怎樣在運行時用名字訪問結構中的域?
      2.17 C語言中有和Pascal的with等價的語句嗎?
      2.18 既然數組名可以用作數組的基地址,為什麼對結構不能這樣?
      2.19 程序運行正確,但退出時卻“core dump ”(核心轉儲)了,怎麼回事?
      聯合
      2.20 結構和聯合有什麼區別?
      2.21 有辦法初始化聯合嗎?
      2.22 有沒有一種自動方法來跟蹤聯合的哪個域在使用?
      枚舉
      2.23 枚舉和一組預處理的#define有什麼不同?
      2.24 枚舉可移植嗎?
      2.25 有什麼顯示枚舉值符號的容易方法嗎?
      位域
      2.26 一些結構聲明中的這些冒號和數字是什麼意思?
      2.27 為什麼人們那麼喜歡用顯式的掩碼和位操作而不直接聲明位域?
      第3章 表達式
      求值順序
      3.1 為什麼這樣的代碼不行?a[i]= i++;
      3.2 使用我的編譯器,下面的代碼int i= 7;printf(\〃%d \〃, i++ * i++);打印出49。不管按什麼順序計算,難道不該是56嗎?
      3.3 對于代碼int i=3;i=i++;不同編譯器給出不同的i值,有的為3,有的為4,哪個是正確的?
      3.4 有這樣一個巧妙的表達式︰a^= b^= a^= b;它不需要臨時變量就可以交換a和b的值。
      3.5 可否用顯式括號來強制執行我所需要的計算順序並控制相關的副作用?就算括號不行,操作符優先級是否能夠控制計算順序呢?
      3.6 可是&&和||操作符呢?我看到過類似while((c = getchar()) != EOF && c != ﹀ ﹀)的代碼
      3.7 是否可以安全地認為,一旦&&和||左邊的表達式已經決定了整個表達式的結果,則右邊的表達式不會被求值?
      3.8 為什麼表達式printf(\〃%d %d\〃, f1(), f2());先調用了f2?我覺得逗號表達式應該確保從左到右的求值順序。
      3.9 怎樣才能理解復雜表達式並避免寫出未定義的表達式?“序列點”是什麼?
      3.10 在a[i] = i++;中,如果不關心a[]的哪一個分量會被寫入,這段代碼就沒有問題,i也的確會增加1,對嗎?
      3.11 人們總是說i=i++的行為是未定義的。可我剛剛在一個ANSI編譯器上嘗試過,其結果正如我所期望的。
      3.12 我不想學習那些復雜的規則,怎樣才能避免這些未定義的求值順序問題呢?
      其他的表達式問題
      3.13 ++i和i++有什麼區別?
      3.14 如果我不使用表達式的值,那我應該用i++還是++i來做自增呢?
      3.15 我要檢查一個數是不是在另外兩個數之間,為什麼if(a b c)不行?
      3.16 為什麼如下的代碼不對?int a=1000, b=1000;long int c=a * b;
      3.17 為什麼下面的代碼總是給出0?double degC, degF;degC= 5.0 / 9 * (degF - 32);
      3.18 需要根據條件把一個復雜的表達式賦給兩個變量中的一個。可以用下面這樣的代碼嗎?((condition) ? a:b)= complicated_expression;
      3.19 我有些代碼包含這樣的表達式。a ? b=c:d 有些編譯器可以接受,有些卻不能。為什麼?
      保護規則
      3.20 “semantics of‘’change in ANSI C”的警告是什麼意思?
      3.21 “無符號保護”和“值保護”規則的區別在哪里?
      第4章 指針
      基本的指針應用
      4.1 指針到底有什麼好處?
      4.2 我想聲明一個指針並為它分配一些空間,但卻不行。這些代碼有什麼問題呢?char *p;*p =malloc(10);
      4.3 *p++自增p還是p所指向的變量?
      指針操作
      4.4 我用指針操作int數組的時候遇到了麻煩。
      4.5 我有一個char *型指針踫巧指向一些int型變量,我想跳過它們。為什麼((int *)p)++;這樣的代碼不行?
      4.6 為什麼不能對void *指針進行算術操作?
      4.7 我有些解析外部結構的代碼,但是它卻崩潰了,顯示出了“unaligned access”(未對齊的訪問)的信息。這是什麼意思?
      作為函數參數的指針
      4.8 我有個函數,它應該接受並初始化一個指針︰void f(int *ip){ static int dummy = 5;ip = &dummy;}但是當我如下調用時︰int *ip;f(ip);調用者的指針沒有任何變化。
      4.9 能否用void ** 通用指針作為參數,使函數模擬按引用傳遞參數?
      4.10 我有一個函數extern intf(int *);,它接受指向int型的指針。我怎樣用引用方式傳入一個常數?調用f(&5);似乎不行。
      4.11 C語言可以“按引用傳參”嗎?
      其他指針問題
      4.12 我看到了用指針調用函數的不同語法形式。到底怎麼回事?
      4.13 通用指針類型是什麼?當我把函數指針賦向void *類型的時候,編譯通不過。
      4.14 怎樣在整型和指針之間進行轉換?能否暫時把整數放入指針變量中,或者相反?
      4.15 我怎樣把一個int變量轉換為char *型?我試了類型轉換,但是不行。
      第5章 空指針
      空指針和空指針常量
      5.1 臭名昭著的空指針到底是什麼?
      5.2 怎樣在程序里獲得一個空指針?
      5.3 用縮寫的指針比較“if(p)”檢查空指針是否有效?如果空指針的內部表達不是0會怎樣?
      NULL 宏
      5.4 NULL是什麼,它是怎麼定義的?
      5.5 在使用非零位模式作為空指針的內部表示的機器上,NULL 是如何定義的?
      5.6 如果NULL定義成#define NULL((char *)0) ,不就可以向函數傳入不加轉換的NULL 了嗎?
      5.7 我的編譯器提供的頭文件中定義的NULL為0L。為什麼?
      5.8 NULL可以合法地用作函數指針嗎?
      5.9 如果NULL和0作為空指針常量是等價的,那我到底該用哪一個呢?
      5.10 但是如果NULL的值改變了,比如在使用非零內部空指針的機器上,用NULL(而不是0)
      不是更好嗎?
      5.11 我曾經使用過一個編譯器,不使用NULL就不能編譯。
      5.12 我用預處理宏#define Nullptr(type)(type *)0幫助創建正確類型的空指針。
      回顧
      5.13 這有點奇怪︰NULL可以確保是0,但空(null)指針卻不一定?
      5.14 為什麼有那麼多關于空指針的疑惑?為什麼這些問題如此頻繁地出現?
      5.15 有沒有什麼簡單點兒的辦法理解所有這些與空指針有關的東西呢?
      5.16 考慮到有關空指針的所有這些困惑,要求它們的內部表示都必須為0不是更簡單嗎?
      5.17 說真的,真有機器用非零空指針嗎,或者不同類型用不同的表示?
      地址0上到底有什麼?
      5.18 運行時的整數值0轉換為指針以後一定是空指針嗎?
      5.19 如何訪問位于機器地址0處的中斷向量?如果我將指針值設為0,編譯器可能會自動將它轉換為非零的空指針內部表示。
      5.20 運行時的“null pointer assignment”錯誤是什麼意思?應該怎樣捕捉它?
      第6章 數組和指針
      數組和指針的基本關系
      6.1 我在一個源文件中定義了char a[6],在另一個源文件中聲明了extern char *a。為什麼不行?
      6.2 可是我听說char a[]和char *a是等價的。是這樣的嗎?
      6.3 那麼,在C語言中“指針和數組等價”到底是什麼意思?
      6.4 既然它們這麼不同,那為什麼作為函數形參的數組和指針聲明可以互換呢?
      數組不能被賦值
      6.5 為什麼不能這樣向數組賦值?extern char *getpass();char str[10];str=getpass(\〃Enter password:\〃);
      6.6 既然不能向數組賦值,那這段代碼為什麼可以呢?int f(char str[]){ if(str[0] == ﹀