編輯推薦
全球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= "w
你必須知道的495個C語言問題 下載 mobi epub pdf txt 電子書