第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
", 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 != '
')的代碼…… 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] == ' ') 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 = &realarray[-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:
"); gets(answer); printf("You typed "%s"
", 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 我將用戶鍵入的字符串讀入數組,然後再顯示齣來。當用戶鍵入
這樣的序列時,為什麼不能正確處理呢? 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) 報齣警告“macro replacement within a string literal ”?它似乎把TRACE(count);擴展成瞭printf("TRACE: %dcount", 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); 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
"調用scanf 從鍵盤讀取數字:int n; scanf("%d
",&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:
ewdir 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不能總在目標串放上終止符' '? 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 ("%fh", 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
",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:
ewdirfile.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
· · · · · · (
收起)