1到4章知識點總結
- 臨近期末考試,感覺C基礎語法(尤其是指標)忘得太多了,所以第一次(也是最後一次)把書從頭到尾仔細地翻了一遍,發現了好多有意思的東西
(或許你可能覺得沒意思QAQ),真長見識了,可惜大部分都不是考點,難受TAT
第一章 概述
- IOCCC國際模糊C程式碼大賽 (International Obfuscated C Code Contest)
v,i,j,k,l,s,a[99];
main()
{
for(scanf("%d",&s); *a-s; v=a[j*=v]-a[i],k=i<s,j+=(v=j<s&&
(!k&&!!printf(2+"\n\n%c"-(!l<<!j)," #Q"[1^v?(1^j)&1:2])&&
++l||a[i]<s&&v&&v-i+j&&v+i-j))&&!(1%=s),v||(i==j?a[i+=k]=0:
++a[i])>=s*k&&++a[--i])
;
}
- 額,這不是亂碼誒。。。
- 這個程式是由Doron Osovlanski 和 Baruch Nissenbaum共同編寫的,其功能是打印出八皇后問題(此問題要求在一個棋盤上放置8個皇后,使得皇后之間不會出現相互“攻擊”的局面)的全部解決方案。
- 事實上,此程式可用於求解皇后數量在4~99範圍內的全部問題,更多的獲獎程式可以到競賽網站www.ioccc.org獲取。
問與答 P5
- lint是做什麼的?
- lint這個名字是如何得來的?
- 如何獲得lint?
- 有沒有辦法在不使用lint的情況下強制編譯器進行更徹底的錯誤檢查?
多級警告? - 我很關心能讓程式儘可能可靠的方法。除了lint和除錯工具以外,還有其他有效的工具嗎?
越界檢查工具 bounds-checker?
記憶體洩漏監測工具 leak-finder?
第二章 基本概念
- 3種註釋方法
(1)/* */
(2)//
(3)#define DEBUG 0
#if DEBUG
#endif
問與答 P21
- GCC是什麼的簡稱?
- 明白了,但GNU又是什麼意思呢?
- GCC有什麼過人之處呢?
- GCC發現程式中錯誤的能力如何?
- 為什麼C語言如此簡明扼要?如果在C語言中用begin和end代替{ 和 },用integer代替int,如此等等,程式似乎更加易讀。
- 在某些C語言書中,main函式的結尾使用的是exit(0)而不是return=0,二者是否一樣呢?
- 如果main函式末尾沒有return語句會產生什麼後果?
- 編譯器是完全移除註釋還是用空格替換掉註釋呢?
- 如何發現程式有沒有未終止的註釋?
- 在一個註釋中巢狀另一個註釋是否合法?
- float型別的名字由何而來?
- 為什麼浮點常量需要以字母f結尾?
- 對識別符號的長度真的沒有限制嗎?
- 縮排時應該使用多少空格?
第三章 格式化輸入/輸出
問與答 P33
- 轉換說明%i也可以用於讀寫整數。%i和%d之間有什麼區別?
- 如果printf函式將%作為轉換說明的開始,那麼如何顯示字元%呢?
- 轉義序列 \t 會使printf函式跳到下一個水平製表符處。如何知道水平製表符到底跳多遠呢?
- 我不能理解scanf函式如何把字元“放回原處”並在以後再次讀取。
- 如果使用者在兩個數之間加入了標點符號(如逗號),scanf函式將如何處理?
第四章 表示式
-
運算子/可能產生意外的結果:當兩個運算元都是整數時,運算子/會丟掉分數部分來“擷取”結果。因此,1/2的結果是0而不是0.5。
-
運算子%要求運算元是整數。如果兩個運算元中有一個不是整數,程式將無法編譯通過。
-
把零用作/或%的右運算元會導致未定義的行為。
-
當運算子/和運算子%用於負運算元時,其結果難以確定。
根據C89標準,如果兩個運算元中有一個為負數,那麼除法的結果既可以向上取整也可以向下取整。(例如,-9/7的結果既可以是-1也可以是-2)
在C89中,如果i或者j是負數,i%j的符號與具體實現有關。(例如,-9%7的值可能是-2或者5)
但是在C99中,除法的結果總是向零擷取的 (因此-9/7的結果是-1),
i%j的值的符號與i的相同(因此-9%7的值是-2)。 -
v = e
如果v和e的型別不同,那麼賦值運算髮生時會把e的值轉化為v的型別。
副作用 -
注意由於存在型別轉換,串在一起的賦值運算的最終結果可能不是預期的結果:
int i;
float f;
f = i = 33.3f;
首先把數值33賦值給變數i,然後把33.0 (而不是預期的33.3)賦值給變數f。 -
既然賦值運算子要求左運算元是左值,那麼在賦值表示式的左側放置任何其他型別的表示式都是不合法的:
12 = i; //WRONG
i + j = 0; //WRONG
-i = j; //WRONG
編譯器會檢測出這種錯誤,並給出諸如“invalid value in assignment"這樣的錯誤訊息。 -
在使用複合賦值運算子時,注意不要交換組成運算子的兩個字元的位置。
交換字元位置產生的表示式也許可以被編譯器接受,但不會有預期的意義。
例如,原打算寫表示式i += j但卻寫成了i =+ j,程式也能夠通過編譯。但是,後一個表示式i =+ j等價於表示式i = (+j ),只是簡單地把 j 的值賦給i。 -
在表示式中,既在某處訪問變數的值又在別處修改它的值是不可取的。
表示式(b = a+2) - (a = 1)既訪問了a的值(為了計算a + 2),又(通過賦值為1)修改了a的值。
有些編譯器在遇到這樣的表示式時會產生一條類似 “operation on‘a’may be undefined"的警告訊息。
問與答 P45
- 我注意到C語言沒有指數運算子。如何求一個數的冪呢?
- 我想把%運算子用於浮點數,但程式無法通過編譯。該怎麼辦?
- 當/運算子和%運算子的運算元是負數時,為什麼規則那麼複雜?
- 如果C語言有左值,那麼它也有右值嗎?
- 前面提到:如果v有副作用,那麼v += e不等價於y = v+e。可以解釋一下嗎?
- C語言為什麼提供++和- -運算子?它們是比其他的自增、自減方法執行得快,還是僅僅更便捷?
- ++和–是否可以處理float型變數?
- 在使用字尾形式的++或–時,何時執行自增或自減操作?
- 丟掉表示式語句的值意味著什麼?
- 但是類似 i = 1; 這樣的語句會如何呢? 我沒發現有什麼東西被丟掉了。