1. 程式人生 > >1到4章知識點總結

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; 這樣的語句會如何呢? 我沒發現有什麼東西被丟掉了。