你必須知道的495個C語言問題[2016年人民郵電出版社出版書籍]

你必須知道的495個C語言問題[2016年人民郵電出版社出版書籍]
更多義項 ▼ 收起列表 ▲

《你必須知道的495個C語言問題》是2016年人民郵電出版社出版的圖書,作者是[美] 史蒂夫 薩米特 (Steve Summit )。

基本信息

【作者】[美]史蒂夫薩米特(SteveSummit)【編輯】傅道坤
【ISBN】978-7-115-37676-3【日期】2016-04
【版次】1【印次】1
【頁數】262頁【字數】393千字
【開本】16【定價】45元

圖書簡介

《你必須知道的495個C語言問題》以問答的形式組織內容,討論了學習或使用C語言的過程中經常遇到的一些問題。書中列出了C用戶經常問的400多個經典問題,涵蓋了初始化、數組、指針、字元串、記憶體分配、庫函式、C預處理器等各個方面的主題,並分別給出了解答,而且結合代碼示例闡明要點。

《你必須知道的495個C語言問題》結構清晰,講解透徹,是各高校相關專業C語言課程很好的教學參考書,也是各層次C程式設計師的實踐指南。

目錄

第1章 聲明和初始化 1

基本類型 1

1.1 我該如何決定使用哪種整數類型? 1

1.2 為什麼不精確定義標準類型的大小? 2

1.3 因為C語言沒有精確定義類型的大小,所以我一般都用typedef定義int16和int32。然後根據實際的機器環境把它們定義為int、short、long等類型。這樣看來,所有的問題都解決了,是嗎? 2

1.4 新的64位機上的64位類型是什麼樣的? 3

指針聲明 3

1.5 這樣的聲明有什麼問題?char *p1, p2; 我在使用p2的時候報錯了。 3

1.6 我想聲明一個指針,並為它分配一些空間,但卻不行。這樣的代碼有什麼問題?char *p; *p=malloc(10); 4

聲明風格 4

1.7 怎樣聲明和定義全局變數和函式最好? 4

1.8 如何在C中實現不透明(抽象)數據類型? 5

1.9 如何生成“半全局變數”,就是那種只能被部分源檔案中的部分函式訪問的變數? 5

存儲類型 6

1.10 同一個靜態(static)函式或變數的所有聲明都必須包含static存儲類型嗎? 6

1.11 extern在函式聲明中是什麼意思? 6

1.12 關鍵字auto到底有什麼用途? 7

類型定義(typedef) 7

1.13 對於用戶定義類型,typedef 和#define有什麼區別? 7

1.14 我似乎不能成功定義一個鍊表。我試過typedef struct{char *item; NODEPTR next;}* NODEPTR; 但是編譯器報了錯誤信息。難道在C語言中結構不能包含指向自己的指針嗎? 7

1.15 如何定義一對相互引用的結構? 9

1.16 Struct{ } x1;和typedef struct{ } x2; 這兩個聲明有什麼區別? 10

1.17 “typedef int(*funcptr)();”是什麼意思? 10

const 限定詞 10

1.18 我有這樣一組聲明:typedef char *charp; const charp p; 為什麼是p而不是它指向的字元為const? 10

1.19 為什麼不能像下面這樣在初始式和數組維度值中使用const值?const int n=5; int a[n]; 10

1.20 const char *p、char const *p和char *const p有什麼區別? 10

複雜的聲明  11

1.21 怎樣建立和理解非常複雜的聲明?例如定義一個包含N個指向返回指向字元的指針的函式的指針的數組? 11

1.22 如何聲明返回指向同類型函式的指針的函式?我在設計一個狀態機,用函式表示每種狀態,每個函式都會返回一個指向下一個狀態的函式的指針。可我找不到任何方法來聲明這樣的函式——感覺我需要一個返回指針的函式,返回的指針指向的又是返回指針的函式……,如此往復,以至無窮。 12

數組大小 13

1.23 能否聲明和傳入數組大小一致的局部數組,或者由其他參數指定大小的參數數組? 13

1.24 我在一個檔案中定義了一個extern數組,然後在另一個檔案中使用,為什麼sizeof取不到數組的大小? 13

聲明問題 14

1.25 函式只定義了一次,調用了一次,但編譯器提示非法重聲明了。 14

*1.26 main的正確定義是什麼?void main正確嗎? 15

1.27 我的編譯器總在報函式原型不匹配的錯誤,可我覺得沒什麼問題。這是為什麼? 15

1.28 檔案中的第一個聲明就報出奇怪的語法錯誤,可我看沒什麼問題。這是為什麼? 15

1.29 為什麼我的編譯器不允許我定義大數組,如double array[256][256]? 15

命名空間 15

1.30 如何判斷哪些標識符可以使用,哪些被保留了? 15

初始化 18

1.31 對於沒有顯式初始化的變數的初始值可以作怎樣的假定?如果一個全局變數初始值為“零”,它可否作為空指針或浮點零? 18

1.32 下面的代碼為什麼不能編譯? intf(){char a[]="Hello, world!";} 18

*1.33 下面的初始化有什麼問題?編譯器提示“invalid initializers ”或其他信息。char *p=malloc(10); 19

1.34 char a[]= "string literal";和char *p="string literal"; 初始化有什麼區別?當我向p[i] 賦值的時候,我的程式崩潰了。 19

1.35 char a{[3]}= "abc"; 是否合法? 20

1.36 我總算弄清楚函式指針的聲明方法了,但怎樣才能初始化呢? 20

1.37 能夠初始化聯合嗎? 20

第2章 結構、聯合和枚舉 21

結構聲明 21

2.1 struct x1{ };和typedef struct{ }x2; 有什麼不同? 21

2.2 這樣的代碼為什麼不對?struct x{ }; x thestruct; 22

2.3 結構可以包含指向自己的指針嗎? 22

2.4 在C語言中用什麼方法實現抽象數據類型最好? 22

*2.5 在C語言中是否有模擬繼承等面向對象程式設計特性的好方法? 22

2.6 為什麼聲明extern f(struct x *p); 給我報了一個晦澀難懂的警告信息? 23

2.7 我遇到這樣聲明結構的代碼:struct name {int namelen; char namestr[1];};然後又使用一些記憶體分配技巧使namestr數組用起來好像有多個元素,namelen記錄了元素個數。它是怎樣工作的?這樣是合法的和可移植的嗎? 23

2.8 我聽說結構可以賦給變數也可以對函式傳入和傳出。為什麼K&R1卻明確說明不能這樣做? 25

2.9 為什麼不能用內建的==和!=操作符比較結構?  26

2.10 結構傳遞和返回是如何實現的? 26

2.11 如何向接受結構參數的函式傳入常量值?怎樣創建無名的中間的常量結構值? 26

2.12 怎樣從/向數據檔案讀/寫結構? 27

結構填充 27

2.13 為什麼我的編譯器在結構中留下了空洞?這導致空間浪費而且無法與外部數據檔案進行“二進制”讀寫。能否關掉填充,或者控制結構域的對齊方式? 27

2.14 為什麼sizeof返回的值大於結構大小的期望值,是不是尾部有填充? 28

2.15 如何確定域在結構中的位元組偏移量? 28

2.16 怎樣在運行時用名字訪問結構中的域? 29

2.17 C語言中有和Pascal的with等價的語句嗎?  29

2.18 既然數組名可以用作數組的基地址,為什麼對結構不能這樣? 29

2.19 程式運行正確,但退出時卻“core dump ”(核心轉儲)了,怎么回事? 29

聯合 30

2.20 結構和聯合有什麼區別? 30

2.21 有辦法初始化聯合嗎? 30

2.22 有沒有一種自動方法來跟蹤聯合的哪個域在使用? 30

枚舉 31

2.23 枚舉和一組預處理的#define有什麼不同?  31

2.24 枚舉可移植嗎? 31

2.25 有什麼顯示枚舉值符號的容易方法嗎? 31

位域 31

2.26 一些結構聲明中的這些冒號和數字是什麼意思? 31

2.27 為什麼人們那么喜歡用顯式的掩碼和位操作而不直接聲明位域? 32

第3章 表達式  33

求值順序 33

3.1 為什麼這樣的代碼不行?a[i]= i++; 33

3.2 使用我的編譯器,下面的代碼int i= 7; printf("%d\n", i++ * i++); 列印出49。不管按什麼順序計算,難道不該是56嗎? 33

3.3 對於代碼int i=3; i=i++; 不同編譯器給出不同的i值,有的為3,有的為4,哪個是正確的? 34

*3.4 有這樣一個巧妙的表達式:a^= b^= a^= b; 它不需要臨時變數就可以交換a和b的值。 34

3.5 可否用顯式括弧來強制執行我所需要的計算順序並控制相關的副作用?就算括弧不行,操作符優先權是否能夠控制計算順序呢? 35

3.6 可是&&和||操作符呢?我看到過類似while((c = getchar()) != EOF && c != '\n')的代碼…… 35

3.7 是否可以安全地認為,一旦&&和||左邊的表達式已經決定了整個表達式的結果,則右邊的表達式不會被求值? 36

3.8 為什麼表達式printf("%d %d", f1(), f2()); 先調用了f2?我覺得逗號表達式應該確保從左到右的求值順序。 36

3.9 怎樣才能理解複雜表達式並避免寫出未定義的表達式?“序列點”是什麼? 36

3.10 在a[i] = i++;中,如果不關心a[]的哪一個分量會被寫入,這段代碼就沒有問題,i也的確會增加1,對嗎? 38

3.11 人們總是說i=i++的行為是未定義的。可我剛剛在一個ANSI編譯器上嘗試過,其結果正如我所期望的。 38

3.12 我不想學習那些複雜的規則,怎樣才能避免這些未定義的求值順序問題呢? 38

其他的表達式問題 39

*3.13 ++i和i++有什麼區別? 39

3.14 如果我不使用表達式的值,那我應該用i++還是++i來做自增呢? 39

3.15 我要檢查一個數是不是在另外兩個數之間,為什麼if(a b c)不行? 40

3.16 為什麼如下的代碼不對?int a=1000, b=1000; long int c=a * b; 40

3.17 為什麼下面的代碼總是給出0?double degC, degF; degC= 5.0 / 9 * (degF - 32); 40

3.18 需要根據條件把一個複雜的表達式賦給兩個變數中的一個。可以用下面這樣的代碼嗎?((condition) ? a : b)= complicated_expression; 41

3.19 我有些代碼包含這樣的表達式。a ? b=c : d 有些編譯器可以接受,有些卻不能。為什麼? 41

保護規則 42

3.20 “semantics of‘’change in ANSI C”的警告是什麼意思? 42

3.21 “無符號保護”和“值保護”規則的區別在哪裡? 42

第4章 指針 45

基本的指針套用 45

4.1 指針到底有什麼好處? 45

4.2 我想聲明一個指針並為它分配一些空間,但卻不行。這些代碼有什麼問題呢?char *p; *p =malloc(10); 45

4.3 *p++自增p還是p所指向的變數? 46

指針操作 46

4.4 我用指針操作int數組的時候遇到了麻煩。 46

4.5 我有一個char *型指針碰巧指向一些int型變數,我想跳過它們。為什麼((int *)p)++; 這樣的代碼不行? 47

4.6 為什麼不能對void *指針進行算術操作? 47

4.7 我有些解析外部結構的代碼,但是它卻崩潰了,顯示出了“unaligned access”(未對齊的訪問)的信息。這是什麼意思? 47

作為函式參數的指針 47

4.8 我有個函式,它應該接受並初始化一個指針:void f(int *ip){ static int dummy = 5; ip = &dummy;}但是當我如下調用時:int *ip; f(ip); 調用者的指針沒有任何變化。 47

4.9 能否用void ** 通用指針作為參數,使函式模擬按引用傳遞參數?  48

4.10 我有一個函式extern intf(int *); ,它接受指向int型的指針。我怎樣用引用方式傳入一個常數?調用f(&5);似乎不行。 49

4.11 C語言可以“按引用傳參”嗎? 50

其他指針問題 50

4.12 我看到了用指針調用函式的不同語法形式。到底怎么回事? 50

4.13 通用指針類型是什麼?當我把函式指針賦向void *類型的時候,編譯通不過。 51

4.14 怎樣在整型和指針之間進行轉換?能否暫時把整數放入指針變數中,或者相反? 51

*4.15 我怎樣把一個int變數轉換為char *型?我試了類型轉換,但是不行。 52

第5章 空指針  53

空指針和空指針常量 53

5.1 臭名昭著的空指針到底是什麼? 53

5.2 怎樣在程式里獲得一個空指針? 54

5.3 用縮寫的指針比較“if(p)”檢查空指針是否有效?如果空指針的內部表達不是0會怎樣? 55

NULL 宏 56

5.4 NULL是什麼,它是怎么定義的? 56

5.5 在使用非零位模式作為空指針的內部表示的機器上,NULL 是如何定義的? 56

5.6 如果NULL定義成#define NULL((char *)0) ,不就可以向函式傳入不加轉換的NULL 了嗎? 57

5.7 我的編譯器提供的頭檔案中定義的NULL為0L。為什麼? 57

5.8 NULL可以合法地用作函式指針嗎? 57

5.9 如果NULL和0作為空指針常量是等價的,那我到底該用哪一個呢? 58

5.10 但是如果NULL的值改變了,比如在使用非零內部空指針的機器上,用NULL(而不是0)

不是更好嗎? 58

5.11 我曾經使用過一個編譯器,不使用NULL就不能編譯。 58

5.12 我用預處理宏#define Nullptr(type)(type *)0幫助創建正確類型的空指針。 59

回顧 59

5.13 這有點奇怪:NULL可以確保是0,但空(null)指針卻不一定? 59

5.14 為什麼有那么多關於空指針的疑惑?為什麼這些問題如此頻繁地出現? 60

5.15 有沒有什麼簡單點兒的辦法理解所有這些與空指針有關的東西呢? 60

5.16 考慮到有關空指針的所有這些困惑,要求它們的內部表示都必須為0不是更簡單嗎? 60

5.17 說真的,真有機器用非零空指針嗎,或者不同類型用不同的表示? 61

地址0 上到底有什麼? 61

5.18 運行時的整數值0轉換為指針以後一定是空指針嗎? 61

5.19 如何訪問位於機器地址0處的中斷向量?如果我將指針值設為0,編譯器可能會自動將它轉換為非零的空指針內部表示。 62

5.20 運行時的“null pointer assignment”錯誤是什麼意思?應該怎樣捕捉它? 62

第6章 數組和指針 63

數組和指針的基本關係 63

6.1 我在一個源檔案中定義了char a[6],在另一個源檔案中聲明了extern char *a。為什麼不行? 63

6.2 可是我聽說char a[]和char *a是等價的。是這樣的嗎? 63

6.3 那么,在C語言中“指針和數組等價”到底是什麼意思? 64

6.4 既然它們這么不同,那為什麼作為函式形參的數組和指針聲明可以互換呢? 65

數組不能被賦值 66

6.5 為什麼不能這樣向數組賦值?extern char *getpass(); char str[10]; str=getpass("Enter password:"); 66

6.6 既然不能向數組賦值,那這段代碼為什麼可以呢?int f(char str[]){ if(str[0] == '\0') str="none";…} 66

6.7 如果你不能給它賦值,那么數組如何能成為左值呢? 66

回顧 67

6.8 現實地講,數組和指針的區別是什麼? 67

6.9 有人跟我講,數組不過是常指針。這樣講準確嗎? 67

6.10 我還是很困惑。到底指針是一種數組,還是數組是一種指針? 67

6.11 我看到一些“搞笑”的代碼,包含5["abcdef"]這樣的“表達式”。這為什麼是合法的C語言表達式呢? 68

數組的指針  68

6.12 既然數組引用會退化為指針,如果array是數組,那么array和&array又有什麼區別呢? 68

6.13 如何聲明一個數組的指針? 69

動態數組分配 70

6.14 如何在運行時設定數組的大小?怎樣才能避免固定大小的數組? 70

6.15 我如何聲明大小和傳入的數組一樣的局部數組? 70

6.16 如何動態分配多維數組? 71

6.17 有個很好的竅門,如果我這樣寫:int realarray[10]; int *array = ℜarray[-1]; 我就可以把“array”當作下標從1 開始的數組。 72

函式和多維數組 73

6.18 當我向一個接受指針的指針的函式傳入二維數組的時候,編譯器報錯了。 73

6.19 我怎樣編寫接受編譯時寬度未知的二維數組的函式? 74

6.20 我怎樣在函式參數傳遞時混用靜態和動態多維數組? 74

數組的大小  75

6.21 當數組是函式的參數時,為什麼sizeof不能正確報告數組的大小? 76

6.22 如何在一個檔案中判斷聲明為extern的數組的大小(例如,數組定義和大小在另一個檔案中)?sizeof操作符似乎不行。 76

6.23 sizeof返回的大小是以位元組計算的,怎樣才能判斷數組中有多少個元素呢? 76

第7 章 記憶體分配 77

基本的記憶體分配問題 77

7.1 為什麼這段代碼不行?char *answer; printf("Type something:\n"); gets(answer); printf("You typed \"%s\"\n", answer); 77

7.2 我的strcat() 不行。我試了下面的代碼:char *s1= "Hello,"; char *s2= "world!"; char *s3= strcat(s1, s2);但是我得到了奇怪的結果。 78

7.3 但是strcat的文檔說它接受兩個char *型參數。我怎么知道(空間)分配的事情呢? 78

*7.4 我剛才試了這樣的代碼:char *p; strcpy(p, "abc");它運行正常。怎么回事?為什麼它沒有出錯? 79

*7.5 一個指針變數分配多少記憶體? 79

7.6 我使用fgets將檔案的所有行讀入一個數組,為什麼讀入的每一行都是最後一行的內容呢? 79

7.7 我有個函式,本該返回一個字元串,但當它返回調用者的時候,返回的字元串卻是垃圾信息。

為什麼?  80

*7.8 那么返回字元串或其他聚集的正確方法是什麼呢? 81

調用malloc 81

7.9 為什麼在調用malloc()時報出了“waring: assignment of pointer from integer lacks a cast”? 81

7.10 為什麼有些代碼小心翼翼地把malloc返回的值轉換為分配的指針類型? 81

*7.11 在調用malloc()的時候,錯誤“不能把void * 轉換為int * ”是什麼意思? 82

7.12 我看到下面這樣的代碼:char *p = malloc(strlen(s) + 1); strcpy(p,s); 難道不應該是malloc ((strlen(s) + 1) * sizeof(char)) 嗎? 82

7.13 我為malloc寫了一個小小的封裝函式。它為什麼不行? 82

7.14 我想聲明一個指針並向它分配一些記憶體,但是不行。這樣的代碼有什麼問題?char *p; *p = malloc(10); 82

7.15 我如何動態分配數組? 83

7.16 怎樣判斷還有多少記憶體? 83

7.17 malloc(0)是返回空指針還是指向0個位元組的指針? 83

7.18 我聽說有的作業系統在程式使用的時候才真正分配malloc申請的記憶體。這合法嗎? 83

有關malloc 的問題 83

7.19 為什麼malloc返回了離譜的指針值?我的確讀過問題7.9,而且也在調用之前包含了extern void *malloc();聲明。  83

7.20 我用一行這樣的代碼分配一個巨大的數組,用於數值運算:double *array = malloc (256 *256 *sizeof(double));malloc()並沒有返回空指針,但是程式運行得有些奇怪,好像改寫了某些記憶體,或者malloc()並沒有分配我申請的那么多記憶體。為什麼? 84

7.21 我的PC機有8兆記憶體。為什麼我只能分配640K左右的記憶體? 84

7.22 我的應用程式非常依賴數據結構的節點的動態分配,而malloc/free的代價成了瓶頸。我該怎么做? 84

7.23 我的程式總是崩潰,顯然發生在malloc內部的某個地方。但是我看不出哪裡有問題。是malloc有bug嗎? 84

釋放記憶體 85

7.24 動態分配的記憶體一旦釋放之後就不能再使用,是吧? 85

7.25 為什麼在調用free()之後指針沒有變空?使用(賦值、比較)釋放之後的指針有多么不安全? 86

7.26 當我調用malloc()為一個函式的局部指針分配記憶體時,我還需要用free()顯式地釋放嗎? 86

7.27 我在分配一些結構,它們包含指向其他動態分配的對象的指針。我在釋放結構的時候,還需要釋放每一個下級指針嗎? 86

7.28 我必須在程式退出之前釋放分配的所有記憶體嗎? 86

7.29 我有個程式分配了大量的記憶體,然後又釋放了。但是從作業系統看,記憶體的占用率卻並沒有變回去。 87

分配記憶體塊的大小 87

7.30 free()怎么知道有多少位元組需要釋放? 87

7.31 那么我能否查詢malloc包,以查明可分配的最大塊是多大? 87

7.32 為什麼sizeof不能告訴我它所指的記憶體塊的大小? 87

其他分配函式 88

7.33 (像問題6.14中那樣)動態分配數組之後,還能改變它的大小嗎? 88

7.34 向realloc()的第一個參數傳入空指針合法嗎?你為什麼要這樣做? 89

7.35 calloc()和malloc()有什麼區別?應該用哪一個?利用calloc 的零填充功能安全嗎?free()可以釋放calloc()分配的記憶體嗎,還是需要一個cfree()?  90

7.36 alloca是什麼?為什麼不提倡使用它? 91

第8章 字元和字元串 92

8.1 為什麼strcat(string, '!'); 不行? 92

8.2 我想檢查一個字元串是否跟某個值匹配。為什麼這樣不行?if(string == "value") 92

8.3 如果我可以寫char a[] = "Hello, world!"; 那為什麼不能寫char a[14]; a = "Hello, world!"; 93

8.4 為什麼我的strcat 不行?我試了char *s1="Hello,"; char *s2="world!"; char *s3 =strcat(s1, s2);可得到的結果很奇怪。 93

8.5 char a[]= "string literal"; 和char *p= "string literal"; 初始化有什麼區別?當我對p[i]賦值的時候,程式崩潰了。 93

8.6 我怎么得到與字元相對應的數字(即ASCII 或其他字元集下的)值?反過來又該怎么做? 94

8.7 C語言有類似其他語言的"substr"(提取子串)這樣的函式嗎? 94

8.8 我將用戶鍵入的字元串讀入數組,然後再顯示出來。當用戶鍵入\n這樣的序列時,為什麼不能正確處理呢? 94

8.9 我注意到sizeof('a')是2而不是1(即不是sizeof(char)),是不是我的編譯器有問題? 94

8.10 我正開始考慮多語言字元集的問題。是否有必要擔心sizeof(char)會被定義為2,以便表達16位的字元集呢? 95

第9章 布爾表達式和變數 96

9.1 C語言中布爾值該用什麼類型?為什麼它不是一個標準類型?我應該用#define或enum定義真值和假值嗎? 96

9.2 既然在C 語言中所有的非零值都被看作“真”,那是不是把TRUE 定義為1很危險?如果某個內建的函式或關係操作符“返回”不是1的其他值怎么辦?  97

9.3 當p是指針時,if(p)是合法的條件表達式嗎? 98

9.4 我該使用像TRUE和FALSE這樣的符號名稱還是直接用1和0來作布爾常量? 98

9.5 我準備使用的一個第三方頭檔案定義了自己的TRUE和FALSE,它們跟我已經開發的部分不兼容。我該怎么辦? 98

第10章 C預處理器 99

宏定義 99

10.1 我想定義一些函式式的宏,例如:#define square(x)x * x但它們並不總是正確的。為什麼? 99

10.2 這裡有一些的預處理宏,使用它們,我可以寫出更像Pascal的C代碼。你覺得怎么樣? 100

10.3 怎么寫一個交換兩個值的通用宏?  101

10.4 書寫多語句宏的最好方法是什麼?  101

10.5 用typdef和預處理宏生成用戶定義類型有什麼區別? 102

頭檔案 102

10.6 我第一次把一個程式分成多個源檔案,我不知道該把什麼放到.c檔案,把什麼放到.h檔案。(“.h”到底是什麼意思?) 102

10.7 可以在一個頭檔案中包含另一頭檔案嗎? 103

10.8 完整的頭檔案搜尋規則是怎樣的?  104

10.9 我在檔案的第一個聲明就遇到奇怪的語法錯誤,但是看上去沒什麼問題。 104

10.10 我使用了來自兩個不同的第三方庫的頭檔案,它們都定義了相同的宏,如TRUE、FALSE、Min()和Max()等,但是它們的定義相互衝突,而且跟我在自己的頭檔案中的定義也有衝突。我該怎么辦? 104

10.11 我在編譯一個程式,看起來我好像缺少需要的一個或多個頭檔案。誰能發給我一份? 105

條件編譯  105

10.12 怎樣構造比較字元串的#if預處理表達式? 105

10.13 sizeof操作符可以用在#if預處理指令中嗎? 106

10.14 我可以像這樣在#define行里使用#ifdef來定義兩個不同的東西嗎? 106

10.15 對typedef的類型定義有沒有類似#ifdef的東西? 106

10.16 我如何用#if表達式來判斷機器是高位元組在前還是低位元組在前? 107

10.17 為什麼在我用#ifdef關掉的代碼行中報出了奇怪的語法錯誤? 107

10.18 我拿到了一些代碼,裡邊有太多的#ifdef。我不想使用預處理器把所有的#include 和#ifdef都擴展開,有什麼辦法只保留一種條件的代碼呢? 107

10.19 如何列出所有的預定義宏? 107

奇異的處理 108

10.20 我有些舊代碼,試圖用這樣的宏來構造標識符:#define Paste(a, b) a/**/b 但是現在不行了。為什麼? 108

10.21 我有一個舊宏:#define CTRL(c) ('c' & 037)現在不能用了。為什麼? 108

10.22 為什麼宏#define TRACE(n) printf("TRACE: \%d\n", n) 報出警告“macro replacement within a string literal ”?它似乎把TRACE(count);擴展成了printf("TRACE: \%d\count", count); 109

10.23 如何在宏擴展的字元串字面量中使用宏參數? 109

10.24 我想用ANSI 的“字元串化”預處理操作符#將符號常量的值放入訊息中,但它總是對宏名稱而不是它的值進行字元串化。這是什麼原因? 109

10.25 我想用預處理器做某件事情,但卻不知道如何下手。 110

可變參數列表的宏 110

10.26 怎樣寫可變參數宏?如何用預處理器“關掉”具有可變參數的函式調用? 110

10.27 如何在通用的調試宏中包含__FILE__和__LINE__宏? 111

第11章 ANSI/ISO標準C 113

標準 113

11.1 什麼是“ANSI C標準”? 113

11.2 如何得到一份標準的副本? 114

*11.3 我在哪裡可以找到標準的更新? 115

函式原型  115

11.4 為什麼我的ANSI編譯器對用float聲明的參數會警告類型不匹配? 115

11.5 能否混用舊式的和新型的函式語法? 116

*11.6 為什麼下述聲明報出了一個奇怪的警告信息“Struct X declared inside parameter list”? extern int f(struct x *p); 116

11.7 有個問題一直困擾著我,它是由這一行printf ("%d", n); 導致的,因為n是個long int型。難道 ANSI 的函式原型不能檢查這種函式的參數不匹配問題嗎? 116

11.8 我聽說必須在調用printf之前包含stdio.h。為什麼? 117

const 限定詞 117

11.9 為什麼不能在初始化和數組維度中使用const值?例如const int n = 5; int a[n]; 117

11.10 “const char *p”、“char const *p ”和“char * const p ”有何區別? 117

11.11 為什麼不能向接受const char ** 的函式傳入char **? 118

11.12 我這樣聲明:typedef char * charp; const charp p; 為什麼是p而不是它所指向的字元為const?  118

main()函式的使用 119

11.13 能否通過將main聲明為void來關掉“main沒有返回值”的警告? 119

11.14 main()的第3個參數envp是怎么回事?  120

11.15 我覺得把main()聲明為void也不會失敗,因為我調用了exit()而不是return,況且我的作業系統也忽略了程式的退出/返回狀態。 120

*11.16 那么到底會出什麼問題?真的有什麼系統不支持void main()嗎? 120

11.17 為什麼以前流行的那些C 語言書總是使用void main()?  120

11.18 在main()中調用exit(status)和返回同樣的status真的等價嗎? 121

預處理功能 121

11.19 我試圖用ANSI“字元串化”預處理操作符'#'向信息中插入符號常量的值,但它字元串化的總是宏的名字而不是它的值。為什麼? 121

11.20 警告信息“warning: macro replacement within a string literal”是什麼意思? 121

11.21 為什麼在我用#ifdef去掉的代碼里出現了奇怪的語法錯誤? 122

11.22 #pragma是什麼,有什麼用? 122

11.23 “#pragma once”什麼意思?我在一些頭檔案中看到了它。 122

其他的ANSI C 問題 123

11.24 char a[3] = "abc";合法嗎?它是什麼意思? 123

11.25 既然對數組的引用會退化為指針,那么,如果array是數組,array和&array之間有什麼區別呢? 123

11.26 為什麼我不能對void *指針進行算術運算? 123

11.27 memcpy()和memmove() 有什麼區別? 124

11.28 malloc(0)有什麼用?返回一個空指針還是指向0位元組的指針? 124

11.29 為什麼ANSI 標準規定了外部標識符的長度和大小寫限制? 125

11.30 noalias是怎么回事?在它身上發生了什麼? 125

老的或非標準的編譯器 125

11.31 為什麼我的編譯器對最簡單的測試程式都報出了一大堆的語法錯誤?對這段代碼的第一行就報錯了:main(int argc. char **argv) { return0; } 125

11.32 為什麼有些 ASNI/ISO 標準庫函式未定義?我明明使用的就是ANSI 編譯器。 126

11.33 誰有可以在舊的C 程式和ANSI C 之間相互轉換的工具,或者自動生成原型的工具? 127

11.34 為什麼聲稱兼容ANSI 的編譯器不能編譯這些代碼?我知道這些代碼是 ANSI 的,因為gcc 可以編譯。 127

兼容性 127

11.35 人們好像有些在意實現定義的(implementation-defined)、不確定的(unspecified)和未定義的(undefined) 行為的區別。它們的區別到底在哪裡? 128

*11.36 一個程式“合法(legal)”、“有效(valid)”或“符合標準的”(conforming )到底是什麼意思? 128

11.37 我很吃驚,ANSI 標準竟然有那么多未定義的東西。標準的唯一任務不就是讓這些東西標準化嗎? 129

11.38 有人說i=i++的行為是未定義的,但是我剛在一個兼容ANSI 的編譯器上測試,得到了我希望的結果。它真的是未定義的嗎? 129

第12章 標準輸入輸出庫 130

基本輸入輸出 130

12.1 這樣的代碼有什麼問題?char c; while((c = getchar()) != EOF) 130

12.2 我有個讀取直到EOF的簡單程式,但是我如何才能在鍵盤上輸入那個“\EOF”呢?我看stdio.h 中定義的EOF 是-1,是不是說我該輸入-1? 131

12.3 為什麼這些代碼把最後一行複製了兩遍?while(!feof(infp)){fgets(buf, MAXLINE, infp); fputs(buf, outfp);} 131

12.4 我用fgets將檔案的每行內容讀入指針數組。為什麼結果所有的行都是最後一行的內容呢? 132

12.5 我的程式的螢幕提示和中間輸出有時沒有在螢幕上顯示,尤其是當我用管道通過另一個程式輸出的時候。為什麼? 132

12.6 我怎樣才能不等待回車鍵而一次輸入一個字元? 132

printf格式 132

12.7 如何在printf 的格式串中輸出一個'%'字元?我試過\%,但是不行。 132

12.8 為什麼這么寫不對?long int n = 123456; printf("%d\n", n); 133

12.9 有人告訴我不能在printf 中使用%lf。為什麼printf() 用%f輸出double 型,而scanf 卻用%lf 呢? 133

*12.10 對於size_t 那樣的類型定義,當我不知道它到底是long 還是其他類型的時候,我應該使用什麼樣的printf格式呢? 134

12.11 如何用printf 實現可變的域寬度?就是說,我想在運行時確定寬度而不是使用%8d? 134

12.12 如何輸出在千位上用逗號隔開的數字?貨幣格式的數字呢? 135

12.13 為什麼scanf("%d", i) 調用不行? 136

*12.14 為什麼char s[30]; scamf("%s", s); 不用&也可以?我原以為傳給scanf的每個變數都要帶&。 136

12.15 為什麼這些代碼不行?double d; scanf("%f", &d); 136

12.16 為什麼這段代碼不行?short int s; scanf("%d", &s); 136

12.17 怎樣在scanf 格式串中指定可變的寬度?  136

12.18 怎樣從特定格式的數據檔案中讀取數據?怎樣讀入10個float 而不用使用包含10次%f的奇怪格式?如何將一行的任意多個域讀入一個數組中? 137

scanf問題 138

12.19 我像這樣用"%d\n"調用scanf 從鍵盤讀取數字:int n; scanf("%d\n",&n); printf("you typed %d\ n", n);好像要多輸入一行才返回。為什麼? 138

12.20 我用scanf 和%d讀取一個數字,然後再用gets() 讀取字元串,但是編譯器好像跳過了gets() 調用!  139

12.21 我發現如果堅持檢查返回值以確保用戶輸入的是我期待的數值,則scanf 的使用會安全很多。但有的時候好像會陷入無限循環。為什麼? 139

12.22 為什麼大家都說不要使用scanf?那我該用什麼來代替呢? 140

其他stdio 函式 141

12.23 我怎樣才知道對於任意的sprintf 調用需要多大的目標緩衝區?怎樣才能避免sprintf 目標緩衝區溢出? 141

12.24 sprintf的返回值是什麼?是int 還是char *? 142

12.25 為什麼大家都說不要使用gets? 142

12.26 我覺得我應該在一長串的printf 調用之後檢查errno ,以確定是否有失敗的調用。為什麼當我將輸出重定向到檔案的時候會輸出奇怪的“printf failed: Not a typewriter ”信息? 142

12.27 fgetops/fsetops和ftell/fseek之間有什麼區別?fgetops和fsetops 到底有什麼用處? 143

12.28 如何清除用戶的多餘輸入,以防止在下一個提示符下讀入?用fflush(stdin) 可以嗎? 143

打開和操作檔案 144

12.29 我寫了一個函式用來打開檔案:myfopen(char *filename, FILE *fp){fp = fopen(filename, "r");}可我這樣調用的時候:FILE *infp; myfopen("filename.dat", infp);,infp 指針並

沒有正確設定。為什麼? 144

12.30 連一個最簡單的fopen調用都不成功!這個調用有什麼問題?FILE *fp = fopen(filename, 'r'); 145

12.31 為什麼我不能用完整路徑名打開一個檔案?這個調用總是失敗:fopen("c:\newdir\ file. dat", "r"); 145

12.32 我想用fopen模式"r+"打開一個檔案,讀出一個字元串,修改之後再寫入,從而就地更新一個檔案。可是這樣不行。為什麼? 145

12.33 如何在檔案中間插入或刪除一行(一條記錄)? 145

12.34 怎樣從打開的流中恢復檔案名稱? 145

重定向stdin 和stdout  146

12.35 怎樣在程式里把stdin或stdout重定向到檔案? 146

12.36 一旦使用freopen之後,怎樣才能恢復原來的stdout (或stdin)? 146

12.37 如何判斷標準輸入或輸出是否經過了重定向,即是否在命令行上使用了“”或“”? 147

12.38 我想寫個像"more"那樣的程式。怎樣才能在stdin 被重定向之後再回到互動鍵盤? 147

*12.39 怎樣同時向兩個地方輸出,如同時輸出到螢幕和檔案? 147

“二進制”輸入輸出 148

12.40 我希望按位元組在記憶體和檔案之間直接讀寫數字,而不像fprintf和fscanf進行格式化。我該怎么辦? 148

12.41 怎樣正確地讀取二進制檔案?有時看到0x0a和0x0d容易混淆,而且如果數據中包含0x1a的話,我好像會提前遇到EOF。 148

12.42 我在寫一個二進制檔案的“過濾器”,但是stdin和stdout卻被作為文本流打開了。怎樣才能把它們的模式改為二進制? 148

12.43 文本和二進制輸入輸出有什麼區別? 149

12.44 如何在數據檔案中讀寫結構? 149

12.45 怎樣編寫符合舊的二進制數據格式的代碼? 149

第13章 庫函式 151

字元串函式 151

13.1 怎樣把數字轉為字元串(與atoi相反)?有itoa函式嗎? 151

13.2 為什麼strncpy不能總在目標串放上終止符'\0'? 152

13.3 C 語言有類似於其他語言中的“substr ”(取出子串)的例程嗎? 152

13.4 怎樣把一個字元串中所有字元轉換成大寫或小寫? 153

13.5 為什麼有些版本的toupper對大寫字元會有奇怪的反應?為什麼有的代碼在調用toupper 前先調用islower? 153

13.6 怎樣將字元串分割成用空白分隔的欄位?怎樣實現類似main 處理argc和argv的過程? 153

13.7 哪裡可以找到處理正則表達式或通配符匹配的代碼? 155

排序 156

13.8 我想用strcmp作為比較函式,調用qsort對一個字元串數組排序,但是不行。為什麼? 156

13.9 我想用qsort()對一個結構數組排序。我的比較函式接受結構指針,但是編譯器認為這個函式不是qsort需要的類型。我要怎樣轉換這個函式指針才能避免這樣的警告? 156

13.10 怎樣對一個鍊表排序? 158

13.11 怎樣對大於記憶體容量的數據排序? 158

日期和時間 159

13.12 怎樣在C 程式中取得當前日期或時間? 159

13.13 我知道庫函式localtime可以把time_t轉換成結構struct tm,而ctime可以把time_t轉換成為可列印的字元串。怎樣才能進行反向操作,把struct tm或一個字元串轉換成time_t?  159

13.14 怎樣在日期上加n天?怎樣取得兩個日期的時間間隔? 160

隨機數 162

13.15 怎么生成一個隨機數? 162

13.16 怎樣獲得某一範圍內的隨機整數? 163

13.17 每次執行程式,rand都返回相同的數字序列。為什麼? 164

13.18 我需要隨機的真/假值,所以我就直接用rand()%2,可是我得到交替的0, 1, 0, 1, 0 …。為什麼? 164

13.19 如何獲取根本不重複的隨機數? 165

13.20 怎樣產生常態分配或高斯分布的隨機數?  165

13.21 我在移植一個程式,裡邊調用了一個函式drand48 ,而我的庫又沒有這個。這是個什麼函式? 167

其他庫函式 168

13.22 exit(status)是否真的跟從main 函式返回status 等價? 168

13.23 memcpy和memmove 有什麼區別? 168

13.24 我想移植這箇舊程式。為什麼報出這些“undefined external”錯誤:index? 、rindex?、bcopy?、bcmp?、bzero??  168

13.25 我不斷得到庫函式未定義錯誤,但是我已經包含了所有用到的頭檔案了。 168

13.26 雖然我在連線時明確地指定了正確的函式館,我還是得到庫函式未定義錯誤。 168

13.27 一個最簡單的程式,不過在一個視窗里列印出“Hello,World”,為什麼會編譯出巨大的可執行代碼(數百K)?我該少包含一些頭檔案嗎? 169

13.28 連線器報告_end未定義代表什麼意思? 169

*13.29 我的編譯器提示printf未定義!這怎么可能? 169

第14章 浮點運算 170

14.1 一個float變數賦值為3.1時,為什麼printf輸出的值為3.0999999? 170

14.2 我想計算一些平方根,我把程式簡化成這樣:main(){printf ("%f\h", sqrt(144.)); 可得到的結果卻是瘋狂的數字。為什麼? 170

14.3 我想做一些簡單的三角函式運算,也包含了math.h ,但連線器總是提示sin、cos這樣的函式未定義。為什麼? 171

14.4 我的浮點數計算程式表現得很奇怪,在不同的機器上給出了不同的結果。為什麼? 171

14.5 有什麼好的方法來檢查浮點數在“足夠接近”情況下的相等? 171

14.6 怎樣取整? 172

14.7 為什麼C語言不提供乘冪的操作符? 173

14.8 為什麼我機器上的math.h沒有預定義常量M_PI? 173

14.9 怎樣將變數置為IEEE NaN(“Not a Number”)或檢測變數是否為NaN及其他特殊值? 173

14.10 如何簡潔地處理浮點異常? 174

14.11 在C語言中如何很好地實現複數? 174

14.12 我要尋找一些實現以下功能的程式原始碼:快速傅立葉變換(FFT)、矩陣算術(乘法、求逆等函式)、複數算術。 175

14.13 Turbo C的程式崩潰,顯示錯誤為“floating point formats not linked”(浮點格式未連線)。我還缺點兒什麼呢? 175

第15章 可變參數列表 176

調用變參函式 176

15.1 為什麼調用printf前必須要包含stdio.h?  176

15.2 為什麼%f可以在printf參數中同時表示float和double?它們難道不是不同類型嗎? 177

15.3 我遇到了一個令人十分受挫的問題,後來發現是這行代碼造成的:printf("%d", n);原來n 是longint型。難道ANSI的函式原型不就是用來防止這類的參數類型不匹配嗎? 177

15.4 怎樣寫一個接受可變參數的函式?  177

15.5 怎樣寫一個函式,像printf那樣接受一個格式串和可變參數,然後再把參數傳給printf去完成大部分工作? 180

15.6 怎樣寫類似scanf的函式,再把參數傳給scanf去完成大部分工作? 180

15.7 我用的是ANSI前的編譯器,沒有stdarg.h檔案。我該怎么辦? 181

提取可變參數 182

15.8 怎樣知道實際上有多少個參數傳入函式? 182

15.9 為什麼編譯器不允許我定義一個沒有固定參數項的可變參數函式? 182

15.10 我有個接受float型的變參函式,為什麼va_arg(argp, float)卻不行? 183

15.11 為什麼va_arg不能得到類型為函式指針的參數? 183

困難的問題 184

15.12 怎樣實現一個可變參數函式,它把參數再傳給另一個可變參數函式? 184

15.13 怎樣調用一個在運行時才構建參數列表的函式? 186

第16 章 奇怪的問題 187

16.1 為什麼這個循環只執行了一次?for(i=start;i end ; i ++);{printf("%d\n",i);} 187

*16.2 遇到不可理解的不合理語法錯誤,似乎大段的程式沒有編譯。 187

*16.3 為什麼過程調用不起作用?編譯器似乎直接跳過去了。 187

16.4 程式在執行之前就崩潰了!(用調試器單步跟蹤,在main函式的第一個語句之前就死了。)為什麼? 188

16.5 程式執行正確,但退出時在main函式的最後一個語句之後崩潰了。為什麼會這樣? 188

16.6 程式在一台機器上運行完美,但在另一台上卻得到怪異的結果。更奇怪的是,增加或去除調試的列印語句,就改變了症狀…… 188

16.7 為什麼下面的代碼會崩潰?char *p = "hello, world!"; p[0] = 'H'; 189

16.8 我有些代碼是用來解析外部結構的,但它卻崩潰了,報了“unaligned access ”(未對齊的訪問)錯誤。這是什麼意思? 190

16.9 “Segmentation violation”、“Bus error”和“General protection fault”是什麼意思? 191

第17章 風格  192

17.1 什麼是C最好的代碼布局風格? 192

17.2 如何在源檔案中合理分配函式? 193

17.3 用if(!strcmp(s1, s2))比較兩個字元串是否相等是個好風格嗎? 193

17.4 為什麼有的人用if(0== x)而不是if(x== 0)? 193

17.5 為什麼有些代碼在每次調用printf 前增加了類型轉換(void)? 194

17.6 既然NULL和0都是空指針常量,我到底該用哪一個? 194

17.7 是該用TRUE和FALSE這樣的符號名稱還是直接用1和0來作布爾常量? 194

17.8 什麼是“匈牙利表示法”(Hungarian Notation )?是否值得一試? 194

17.9 哪裡可以找到“Indian Hill Style Guide ”及其他編碼標準? 194

17.10 有人說goto是邪惡的,永遠都不該用它。這是否太極端了? 195

17.11 人們總是說良好的風格很重要,但當他們使用良好的風格寫出清晰易讀的程式後,又發現程式的效率似乎降低了。既然效率那么重要,是否可以為了效率犧牲一些風格和可讀性呢? 196

第18章 工具和資源 197

18.1 能否列一個常用工具列表? 197

18.2 怎樣捕獲棘手的malloc問題? 198

18.3 有什麼免費或便宜的編譯器可以使用? 198

lint 198

18.4 剛剛輸入完一個程式,但它表現得很奇怪。你能發現有什麼錯誤的地方嗎? 199

18.5 如何關掉lint對每個malloc調用報出的“warning: possible pointer alignment problem”警告訊息? 199

18.6 哪裡可以找到兼容ANSI的lint? 199

18.7 難道ANSI函式原型說明沒有使lint過時嗎? 199

資源 200

18.8 網上有哪些C語言的教程或其他資源? 200

*18.9 哪裡可以找到好的原始碼實例,以供研究和學習? 201

18.10 有什麼好的學習C語言的書?有哪些高級的書和參考? 201

18.11 哪裡能找到K&R的練習答案? 201

18.12 哪裡能找到Numerical Recipes in C 、Plauger的The Standard C Library或Kernighan和Pike的The UNIX Programming Enviroment等書里的源碼? 201

18.13 哪裡可以找到標準C函式館的原始碼? 202

18.14 是否有一個線上的C參考指南? 202

18.15 我需要分析和評估表達式的代碼。從哪裡可以找到? 202

18.16 哪裡可以找到C的BNF或YACC語法?  202

*18.17 誰有C編譯器的測試套件? 203

*18.18 哪裡有一些有用的原始碼片段和例子的收集? 203

*18.19 我需要執行多精度算術的代碼。 203

18.20 在哪裡和怎樣取得這些可自由發布的程式? 203

第19章 系統依賴 205

鍵盤和螢幕I/O 205

19.1 怎樣從鍵盤直接讀入字元而不用等回車鍵?怎樣防止字元輸入時的回顯? 205

19.2 怎樣知道有未讀的字元(如果有,有多少)?另外,如何在沒有字元的時候不阻塞讀入? 209

19.3 怎樣顯示一個在原地更新自己的百分比或“旋轉棒”的進度指示器? 209

19.4 怎樣清屏?怎樣反色輸出?怎樣把游標移動到指定的x, y位置? 210

19.5 怎樣讀入方向鍵、功能鍵? 210

其他I/O 211

19.6 怎樣讀入滑鼠輸入? 211

19.7 怎樣做串口(“comm”)的輸入輸出? 211

19.8 怎樣直接輸出到印表機? 211

19.9 怎樣傳送轉義字元序列控制終端或其他設備? 211

19.10 怎樣做圖形? 212

*19.11 怎樣顯示GIF和JPEG圖像? 212

檔案和目錄 212

19.12 怎樣檢驗一個檔案是否存在?如果請求的輸入檔案不存在,我希望向用戶提出警告。 212

19.13 怎樣在讀入檔案前,知道檔案大小? 213

*19.14 怎樣得到檔案的修改日期和時間? 213

19.15 怎樣原地縮短一個檔案而不用清除或重寫? 213

19.16 怎樣在檔案中插入或刪除一行(或一條記錄)? 214

19.17 怎樣從一個打開的流或檔案描述符得到檔案名稱? 214

19.18 怎樣刪除一個檔案? 214

*19.19 怎樣複製檔案? 215

19.20 為什麼用了詳盡的路徑還不能打開檔案?下面的代碼會返回錯誤。Fopen("c:\newdir\file.dat", "r") 215

*19.21 fopen不讓我打開檔案"$HOME/.profile"和"~/.myrcfile"。 215

*19.22 怎樣制止MS-DOS下令人恐怖的“Abort,Retry,Ignore? ”信息? 215

19.23 遇到“Too many open files(打開檔案太多)”的錯誤,怎樣增加同時打開檔案的允許數目? 215

19.24 如何得到磁碟的可用空間大小? 216

19.25 怎樣在C語言中讀入目錄? 216

19.26 如何創建目錄?如何刪除目錄(及其內容)? 217

訪問原始記憶體 217

19.27 怎樣找出系統還有多少記憶體可用? 217

19.28 怎樣分配大於64K的數組或結構? 217

19.29 錯誤信息“DGROUP data allocation exceeds 64K(DGROUP 數據分配記憶體超過64K)”什麼意思?我應該怎么做?我以為使用了大記憶體模型,就可以使用大於64K的數據! 217

19.30 怎樣訪問位於某特定地址的記憶體(記憶體映射的設備或圖形顯示記憶體)? 218

19.31 如何訪問機器地址0處的中斷向量?如果將指針設為0,編譯器可能把它轉成一個非零的內部空指針值。 218

“系統”命令 219

19.32 怎樣在一個C程式中調用另一個程式(獨立可執行的程式或系統命令)? 219

19.33 如果運行時才知道要執行的命令的參數(檔案名稱等),應該如何調用system? 219

19.34 在MS-DOS上如何得到system返回的準確錯誤狀態? 220

19.35 怎樣調用另一個程式或命令,然後獲取它的輸出? 220

進程環境  220

19.36 怎樣才能發現程式自己的執行檔案的全路徑? 220

19.37 怎樣找出和執行檔案在同一目錄的配置檔案? 221

19.38 進程如何改變它的調用者的環境變數? 221

19.39 如何打開命令行給出的檔案並解析選項?  221

19.40 exit(status)是否真的和從main函式返回同樣的status等價? 221

19.41 怎樣讀入一個對象檔案並跳躍到其中的函式? 221

其他系統相關的操作 222

19.42 怎樣以小於1秒的精度延時或計算用戶回響時間? 222

19.43 怎樣捕獲或忽略control-C這樣的鍵盤中斷? 222

19.44 怎樣簡潔地處理浮點異常? 223

19.45 怎樣使用socket?如何聯網?如何寫客戶/伺服器程式? 223

*19.46 怎樣調用BIOS函式?如何寫ISR?如何創建TSR?  224

*19.47 什麼是“near”和“far”指針? 224

回顧 224

19.48 我不能使用這些非標準、依賴系統的函式,程式需要兼容ANSI! 224

19.49 為什麼這些內容沒有在C語言中進行標準化?任何現實程式都會用到這些東西。 224

第20章 雜項 226

20.1 怎樣從函式返回多個值? 226

20.2 用什麼數據結構存儲文本行最好?我開始用固定大小的char型數組的數組,但是有很多局限。 227

20.3 怎樣打開命令行提到的檔案並處理參數? 229

20.4 如何正確地使用errno? 231

20.5 怎樣寫數據檔案,使之可以在不同字大小、位元組順序或浮點格式的機器上讀入? 232

20.6 怎樣用char *指針指向的函式名調用函式? 232

位和位元組  233

20.7 如何操作各個位? 233

20.8 怎樣實現位數組或集合? 234

20.9 怎樣判斷機器的位元組順序是高位元組在前還是低位元組在前? 235

*20.10 怎樣調換位元組? 236

20.11 怎樣將整數轉換到二進制或十六進制? 237

20.12 可以使用二進制常數(類似0b101010這樣的東西)嗎?printf有二進制的格式說明符嗎? 237

效率 238

20.13 用什麼方法計算整數中為1的位的個數最高效? 238

20.14 怎樣提高程式的效率? 238

20.15 指針真的比數組快嗎?函式調用會拖慢程式多少?++i比i=i+1快嗎? 240

20.16 用移位操作符替換乘法和除法是否有價值? 240

*20.17 人們說編譯器最佳化得很好,我們不再需要為速度而寫彙編了,但我的編譯器連用移位代替i/=2都做不到。 240

*20.18 怎樣不用臨時變數而交換兩個值? 241

switch 語句 241

20.19 switch語句和if/else鏈哪個更高效? 241

20.20 是否有根據字元串進行條件切換的方法? 241

20.21 是否有使用非常量case行標的方法(如範圍或任意的表達式)? 242

各種語言功能 243

20.22 return語句外層的括弧是否真的可選擇?  243

20.23 為什麼C語言的注釋不能嵌套?怎樣注釋掉含有注釋的代碼?引號包含的字元串內的注釋是否合法? 243

20.24 為什麼C語言的操作符不設計得更全面一些?好像還缺了一些^^、&&=和-=這樣的操作符。 244

*20.25 C語言有循環移位操作符嗎? 244

*20.26 C是個偉大的語言還是別的什麼東西?哪個其他語言可以寫出像a+++++b這樣的代碼? 244

20.27 如果賦值操作符是:=,是不是就不容易意外地寫出if(a=b)了? 245

20.28 C語言有和Pascal 的with等價的語句嗎? 245

20.29 為什麼C語言沒有嵌套函式? 245

*20.30 assert是什麼?如何使用? 246

其他語言  246

20.31 怎樣從C中調用FORTRAN(C++、BASIC、Pascal、Ada、LISP)的函式?反之如何? 246

20.32 有什麼程式可以將Pascal或FORTRAN(或LISP、Ada、awk、“老”C)程式轉化為C程式? 246

20.33 C++是C的超集嗎?可以用C++編譯器來編譯C代碼嗎? 247

20.34 我需要用到“近似”的strcmp例程,比較兩個字元串的近似度,並不需要完全一樣。有什麼好辦法? 247

20.35 什麼是散列法? 248

20.36 如何生成正態或高斯分布的隨機數? 248

20.37 如何知道某個日期是星期幾? 249

20.38 (year % 4== 0)是否足以判斷閏年?2000年是閏年嗎? 250

20.39 為什麼tm結構中的tm_sec的範圍是0到61,暗示一分鐘有62秒? 250

瑣事 250

20.40 一個難題:怎樣寫一個輸出自己原始碼的程式? 250

20.41 什麼是“達夫設備”(Duff’s Device)?  251

20.42 下屆國際C語言混亂代碼競賽(International Obfuscated C Code Contest,IOCCC)什麼時候進行?哪裡可以找到當前和以前的獲勝代碼? 251

20.43 K&R1提到的關鍵字entry是什麼? 252

20.44 C的名字從何而來? 252

20.45 “char”如何發音? 252

*20.46 “lvalue”和“rvalue”代表什麼意思? 252

20.47 哪裡可以獲得本書的線上版? 252

術語表 253

參考文獻 261

相關詞條

相關搜尋

熱門詞條

聯絡我們