你必須知道的495個C語言問題

你必須知道的495個C語言問題 pdf epub mobi txt 電子書 下載 2025

[美] 史蒂夫·薩米特(Steve Summit) 著,孫雲,硃群英 譯
圖書標籤:
  • C語言
  • 編程
  • 問題解答
  • 疑難解答
  • 技術
  • 計算機科學
  • 開發
  • 學習
  • 參考書
  • 編程技巧
想要找書就要到 靜流書站
立刻按 ctrl+D收藏本頁
你會得到大驚喜!!
齣版社: 人民郵電齣版社
ISBN:9787115376763
版次:1
商品編碼:11899350
品牌:異步圖書
包裝:平裝
開本:16開
齣版時間:2016-04-01
用紙:膠版紙
頁數:262
正文語種:中文

具體描述

編輯推薦

  全球C語言程序員集體智慧的結晶  全五星好評圖書  解答495個常遇到的C語言問題  作者Summit在本書中提供瞭常遇到的495個C語言問題的答案。本書針對作者在Internet上廣受歡迎的C FAQ列錶進行瞭全麵修訂,迴答瞭400多個問題來闡釋關鍵點並為程序員提供實用指導。對於所有的C程序員來說,本書都是頗受歡迎的參考,它提供瞭準確的答案,有見地的解釋,並輔之以大量的代碼示例來澄清要點。  本書特色:  以實用、具體的方式講解C語言的操作手冊  針對400多個常問到的問題,給齣瞭正確的答案  在實際編寫程序時遇到的真實問題進行瞭詳細描述  針對常被誤解的問題進行瞭澄清:微妙的移植性問題、正確的語言使用、係統特定的問題

內容簡介

  《你必須知道的495個C語言問題》以問答的形式組織內容,討論瞭學習或使用C語言的過程中經常遇到的一些問題。書中列齣瞭C用戶經常問的400多個經典問題,涵蓋瞭初始化、數組、指針、字符串、內存分配、庫函數、C預處理器等各個方麵的主題,並分彆給齣瞭解答,而且結閤代碼示例闡明要點。  《你必須知道的495個C語言問題》結構清晰,講解透徹,是各高校相關專業C語言課程很好的教學參考書,也是各層次C程序員的實踐指南。

作者簡介

  Steve Summit,畢業於麻省理工學院,有15年的C編程經驗。他在Internet上廣受尊重,並且維護著Usenet新聞組comp.lang.c的FAQ列錶。他當前從事C和UNIX的教學工作,並緻力於各種C和UNIX項目,其重點是積極的可移植代碼和接口設計。

目錄

第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

前言/序言


洞悉 C 語言的精髓:深度解析與實戰應用 C 語言,作為一門經典而強大的編程語言,其影響力跨越瞭操作係統、嵌入式係統、遊戲開發乃至高性能計算等諸多領域。理解 C 語言的底層機製、掌握其精妙的設計,是每一位渴望在編程世界中深耕細作的開發者繞不開的必修課。本書旨在帶領讀者超越零散的語法知識,深入 C 語言的核心,構建紮實的理論基礎,並熟練運用其強大的能力解決實際問題。 本書並非簡單羅列 C 語言的語法規則,而是著力於剖析那些隱藏在代碼背後,決定程序效率、健壯性和可維護性的關鍵概念。我們相信,理解“為什麼”比僅僅知道“怎麼做”更為重要。因此,本書將圍繞 C 語言的內在邏輯,從最基礎的內存模型齣發,逐步深入到指針的奧秘、數據結構的巧妙運用、運算符的精細行為,乃至函數調用棧的運行機製。每一個章節都旨在解開 C 語言的“黑箱”,讓讀者真正掌握這門語言的靈魂。 我們首先將目光聚焦於 C 語言的基石——內存管理。 深入理解棧(Stack)與堆(Heap)的區彆與聯係,以及它們在程序運行時的作用,是避免內存泄漏、野指針等常見錯誤的根本。我們將詳細闡述變量的作用域與生命周期,分析局部變量、全局變量、靜態變量以及它們的存儲特性。更重要的是,我們會深入探討動態內存分配與釋放的原理,包括 `malloc`、`calloc`、`realloc` 和 `free` 函數的使用場景、注意事項以及可能齣現的內存碎片問題。通過剖析這些底層機製,讀者將能夠寫齣更加安全、高效的內存管理代碼。 指針,作為 C 語言最強大的工具之一,其深度與廣度是許多初學者感到睏惑的難點。 本書將以一種循序漸進的方式,從指針的基本概念、聲明與解引用開始,逐步過渡到指針與數組、指針與函數、指針與字符串的結閤運用。我們不僅僅會講解如何使用指針,更會深入剖析指針運算的本質,理解指針的地址模型,以及多級指針的復雜邏輯。通過大量的實例,我們將展示如何利用指針高效地訪問和操作數據,以及在鏈錶、樹等復雜數據結構中指針扮演的關鍵角色。理解指針的精髓,將極大地提升 C 語言的編程能力,並為深入學習其他語言打下堅實基礎。 數據結構與算法是 C 語言應用的重要載體。 本書將以 C 語言的特性為齣發點,詳細講解經典數據結構的實現與應用。從最基礎的數組和鏈錶,到棧、隊列、樹(二叉樹、平衡樹)、圖等。我們將不僅提供這些數據結構的 C 語言實現代碼,更會深入分析它們的 time complexity 和 space complexity,以及在不同場景下的優劣勢。例如,在實現鏈錶時,我們將討論單嚮鏈錶、雙嚮鏈錶、循環鏈錶的設計思路;在講解樹結構時,我們會分析二叉搜索樹的插入、刪除、查找操作,並介紹 AVL 樹、紅黑樹等自平衡樹的原理。通過親手實現這些數據結構,讀者將對它們的內部工作原理有更深刻的理解,並能根據實際需求選擇最閤適的數據結構來優化程序性能。 C 語言的運算符是構建錶達式的基礎,但其行為的微妙之處往往容易被忽視。 本書將對 C 語言的各類運算符進行詳盡的解析,包括算術運算符、關係運算符、邏輯運算符、位運算符、賦值運算符以及逗號運算符等。我們會重點關注運算符的優先級與結閤性,解釋錶達式的求值順序,以及自增自減運算符在不同上下文中的行為。尤其值得一提的是,我們將深入剖析位運算符的強大功能,展示如何利用位運算進行高效的數據操作,例如比特位的設置、清除、翻轉,以及快速的乘除運算等。通過對運算符的透徹理解,讀者將能夠寫齣更加精確、高效的代碼,並避免因運算符行為理解偏差而導緻的潛在 bug。 函數是 C 語言程序的基本模塊,而函數調用棧的運行機製是理解程序執行流程的關鍵。 本書將詳細闡述函數調用過程中的棧幀(Stack Frame)概念,包括參數傳遞、局部變量的存儲、返迴地址的保存等。我們將分析遞歸函數的調用機製,解釋其深度限製以及如何避免棧溢齣。此外,本書還將探討函數指針的應用,展示如何實現迴調函數、動態調用函數以及構建更靈活的程序結構。理解函數調用棧,能夠幫助讀者更好地調試程序,分析運行時錯誤,並寫齣結構清晰、易於維護的 C 語言程序。 預處理器和編譯過程是 C 語言程序從源代碼轉化為可執行文件的必經之路。 本書將深入講解 C 預處理器的功能,包括宏定義(包括帶參數宏和不帶參數宏)、條件編譯(`ifdef`、`ifndef`、`if`、`else`、`elif`、`endif`)、文件包含(`include`)以及 `pragma` 指令等。我們將分析宏展開的過程,講解條件編譯在項目構建中的重要作用,以及如何利用文件包含實現代碼的模塊化。同時,本書還將簡要介紹 C 程序的編譯、鏈接過程,幫助讀者理解源代碼經過預處理、編譯、匯編、鏈接最終生成可執行文件的完整流程。 除瞭上述核心概念,本書還將觸及 C 語言在實際應用中的一些重要方麵。 例如,我們將討論結構體(`struct`)和聯閤體(`union`)的定義與使用,分析它們的內存布局以及在數據封裝中的作用。我們將探討枚舉類型(`enum`)的優勢,以及類型轉換(顯式與隱式)的規則與風險。此外,對於一些常見的 C 語言陷阱和易錯點,本書也會進行專門的剖析和總結,幫助讀者提前規避開發過程中的潛在問題。 本書的編寫風格力求清晰、嚴謹,並輔以大量的代碼示例和圖解。 我們希望通過理論與實踐的結閤,使讀者在理解 C 語言抽象概念的同時,也能看到它們在具體代碼中的體現。每一個示例都經過精心設計,旨在突齣某個特定的知識點,並鼓勵讀者動手實踐,親自去驗證和探索。我們相信,掌握 C 語言的精髓,不僅僅是為瞭解決眼前的編程任務,更是為瞭培養一種嚴謹的邏輯思維和解決問題的能力,這種能力將伴隨開發者一生,並在未來的技術道路上發揮至關重要的作用。 本書的目標讀者包括但不限於: 初學者: 希望係統地學習 C 語言,建立紮實的理論基礎,避免走彎路。 有一定 C 語言基礎的開發者: 希望深入理解 C 語言的底層機製,解決開發中遇到的疑難問題,提升代碼質量。 嵌入式係統開發者: 需要深入理解內存管理、指針操作,以優化資源受限環境下的程序性能。 操作係統或底層係統開發者: 需要對 C 語言有精深的掌握,以編寫高效、可靠的係統級代碼。 任何希望提升編程思維和解決問題能力的開發者: C 語言的嚴謹和底層特性是鍛煉編程思維的絕佳訓練場。 閱讀本書,您將獲得: 對 C 語言內存模型和管理的深刻理解。 駕馭指針的信心與能力,將其化為強大的編程工具。 構建和應用經典數據結構的實踐經驗。 清晰掌握 C 語言各類運算符的行為,寫齣精確的代碼。 洞悉函數調用棧的運行機製,有效調試程序。 理解 C 預處理器和編譯流程,更好地管理項目。 掌握 C 語言的常見陷阱和最佳實踐。 提升代碼的效率、健壯性和可維護性。 培養嚴謹的邏輯思維和深入分析問題的能力。 踏上 C 語言的探索之旅,讓本書成為您手中不可或缺的指南。我們將一同揭開 C 語言神秘的麵紗,領略其設計的精妙,掌握其強大的力量,開啓更廣闊的編程視野。

用戶評價

評分

坦白說,我最初購買這本書是抱著試試看的心態,因為我本身對C語言的學習熱情並不是特彆高漲,覺得它相對比較古老。然而,這本書的打開方式卻完全顛覆瞭我的認知。它並沒有采用枯燥的說教模式,而是通過一種問答式的結構,將495個C語言中最核心、最常見、最容易齣錯的問題一一呈現,並且提供瞭清晰、透徹的解答。這種形式非常適閤我這種注意力容易分散的學習者。我可以在零散的時間裏,隨意翻閱其中的某個問題,快速地獲取我需要的知識點。書中對於一些概念的解釋,比如遞歸、結構體、聯閤體等等,都非常形象生動,結閤瞭生活中的例子,讓我能夠輕鬆理解。而且,這本書的題目設置非常巧妙,很多問題都是我曾經在實際編程中遇到過的,或者是我在學習過程中感到睏惑的。這本書就像一個“知識寶庫”,總能找到我需要的答案,並且讓我茅塞頓開。我感覺自己對C語言的理解不再是碎片化的,而是形成瞭一個更加係統、完整的認知體係。

評分

我是一名嵌入式開發工程師,C語言是我的日常工作語言。在我多年的開發生涯中,也接觸過不少C語言相關的書籍,但《你必須知道的495個C語言問題》這本書給我留下瞭非常深刻的印象。它不是一本簡單的語法手冊,更像是一本“C語言黑魔法”的揭秘手冊。書中對於內存模型、數據錶示、浮點數精度、多綫程安全等一些底層細節的講解,是我在其他書籍中很少見到的。例如,書中對於volatile關鍵字的講解,以及它在並發編程中的重要性,讓我對如何編寫綫程安全的C代碼有瞭新的認識。我還特彆喜歡書中關於宏定義的深入探討,以及如何利用它來編寫更高效、更靈活的代碼,這對於嵌入式開發尤為重要。此外,書中還提到瞭一些關於C語言標準和不同編譯器實現差異的分析,這對於我這種需要考慮跨平颱兼容性的開發者來說,非常有價值。這本書讓我意識到,要真正精通C語言,不僅僅是掌握語法,更要理解它背後的運行機製和設計哲學。它確實是一本值得反復研讀的工具書,能夠幫助我解決實際開發中遇到的各種難題。

評分

這本書的價值絕對超齣瞭它的定價。我是一名計算機專業的學生,在學習C語言的過程中,常常會遇到一些“為什麼”的問題,比如為什麼某些代碼寫齣來會有意想不到的結果,或者為什麼在不同的編譯器環境下錶現會略有差異。這本書就像一個經驗豐富的導師,能夠精準地解答我心中的這些疑惑。它並非簡單地羅列“怎麼做”,而是深入地闡述“為什麼這麼做”,以及這樣做的背後原理。書中對類型轉換、運算符優先級、作用域規則等概念的講解,都極其細緻,甚至連一些看似微不足道的細節都進行瞭深入的分析,這對於我這種需要嚴謹對待編程知識的學生來說,非常有幫助。更難得的是,書中還涵蓋瞭一些關於C語言的“最佳實踐”和“陷阱規避”的建議,這讓我能夠在編寫代碼時更加規範,避免一些潛在的錯誤。我發現,通過閱讀這本書,我不僅學會瞭如何寫齣能運行的代碼,更學會瞭如何寫齣高質量、健壯、易於維護的代碼。我強烈推薦給所有正在學習C語言或者希望鞏固C語言基礎的同學們。

評分

這本書的封麵設計非常吸引人,簡潔的配色和醒目的標題立刻抓住瞭我的眼球。我本身是對編程抱有濃厚興趣的初學者,一直想係統地學習C語言,但市麵上的教材往往過於理論化,或者知識點過於零散,讓我難以找到一條清晰的學習路徑。當我翻開這本書,發現它的排版非常清晰,章節劃分邏輯性很強,從最基礎的變量、數據類型,到更復雜的指針、內存管理,再到一些實用的進階技巧,都循序漸進地展開。尤其讓我印象深刻的是,書中並沒有僅僅羅列概念,而是通過大量的實例和代碼片段來講解,這對於我這種“動手派”的學習者來說簡直是福音。每講解完一個知識點,作者都會給齣相應的練習題,並且附帶詳細的解答,這不僅幫助我鞏固瞭所學內容,更能讓我理解不同解法的優劣。我特彆喜歡書中對一些常見易錯點的歸納,這讓我避免瞭不少彎路,也讓我對C語言的理解更加深入。雖然我還沒有完全讀完,但這本書已經成為我學習C語言過程中不可或缺的夥伴,我感覺自己離掌握這門語言又近瞭一大步。

評分

作為一名已經接觸C語言一段時間的開發者,我一直在尋找能夠幫助我提升技術深度和解決實際問題能力的資料。許多技術書籍要麼過於基礎,要麼內容陳舊,要麼就是晦澀難懂。而《你必須知道的495個C語言問題》這本書,則在“深度”和“實用性”之間找到瞭絕佳的平衡點。它沒有停留在錶麵知識的講解,而是深入剖析瞭C語言設計背後的思想,以及一些常被忽視但至關重要的細節。例如,關於指針的講解,書中不僅介紹瞭基本用法,更深入探討瞭指針的各種高級應用,如函數指針、void指針以及它們在動態內存分配和數據結構中的作用。對於內存管理方麵,這本書的闡述也相當到位,通過對malloc、free等函數的詳細解釋,以及內存泄漏的常見原因分析,讓我對如何在C語言中安全有效地管理內存有瞭更深刻的認識。此外,書中關於預處理器、位操作等一些比較底層的概念的講解,也為我打開瞭新的視野,讓我能更好地理解程序的底層運行機製。總而言之,這是一本能夠幫助開發者“內功”提升的寶典,即使是經驗豐富的程序員,也能從中獲益匪淺。

評分

快捷,實惠,一如既往的的好。給京東點贊

評分

很好。。。。。。。。。。。。。。。。。。。

評分

買迴來多多學習吧,很有用。

評分

有一些句子不通順,總體上還是不錯的!

評分

評分

很實用的一本書

評分

不錯的書,我喜歡,買買買,已經幾百本瞭

評分

可以

評分

不錯,講瞭更多平時積纍的問題。

相關圖書

本站所有內容均為互聯網搜尋引擎提供的公開搜索信息,本站不存儲任何數據與內容,任何內容與數據均與本站無關,如有需要請聯繫相關搜索引擎包括但不限於百度google,bing,sogou

© 2025 book.coffeedeals.club All Rights Reserved. 靜流書站 版權所有