天天看點

C語言深度剖析學習錯誤點記錄

0. static修飾變量和函數

static修飾變量,1)限定作用域,本檔案内。全局變量(自定義起,本檔案前面要用需extern聲明),局部變量函數内;2)生命周期,程式運作期間一直儲存。

static修飾函數,限定作用域,本檔案内。

1. enum類型變量大小為4(sizeof),不論enum成員數量。

2. enum成員間用“,”分割,最後一個成員後可不加分隔号。

而struct、union成員間用“;”分割,最後一個成員後要加分隔号。而struct的成員初始化用“,”分割,最後成員後加不加“,”均可。

3. stu_pst為typedef的struct student的類型,const stu_pst stu3和stu_pst const stu4完全等價。資料類型可忽略。

4. {}作用就是打包。

5. const修飾的隻讀變量不能用來作為定義數組的維數,也不能放在case關鍵字後面。

一個參數既可以是const還可以是volatile嗎?解釋為什麼?

核心include/asm-generic/io.h:static inline u8 __raw_readb(const volatile void __iomem *addr)

可以的,例如隻讀的狀态寄存器。它是volatile因為它可能被意想不到地改變。它是const因為程式不應該試圖去修改它。

一個定義為volatile的變量是說這變量可能會被意想不到地改變,這樣,編譯器就不會去假設這個變量的值了。精确地說就是,優化器在用到這個變量時必須每次都小心地重新讀取這個變量的值,而不是使用儲存在寄存器裡的備份。volatile修飾符告訴complier變量值可以以任何不被程式明确指明的方式改變,最常見的例子就是外部端口的值,它的變化可以不用程式内的任何指派語句就有可能改變的,這種變量就可以用volatile來修飾,complier不會優化掉它。

const修飾的變量在程式裡面是不能改變的,但是可以被程式外的東西修改,就象上面說的外部端口的值,如果僅僅使用const,有可能complier會優化掉這些變量,加上volatile就萬無一失了。

6. p為typedef的struct student類型,p+0x1為&p + sizeof(struct student)*1。

7. c語言中,所有非數組形式的資料實參均以傳值形式調用。(對實參做一份拷貝并傳遞給被調用的函數,函數不能修改作為實參的實際變量的值,而隻能修改傳遞給它的那份拷貝)

c語言中,當一維數組作為函數參數的時候,編譯器總是把它解析成一個指向其首元素首位址的指針。

8. 記憶體可分為三個區:靜态區、棧、堆

靜态區:儲存自動全局變量和static變量(包括static全局和局部變量)。靜态區的内容在整個程式的生命周期内都存在,由編譯器在編譯的時候配置設定。

棧:儲存局部變量。棧上的内容隻在函數範圍記憶體在,當函數運作結束時,這些内容也會自動被銷毀。其特點就是效率高,但空間大小有限。

堆:由malloc系列函數或new操作符配置設定的記憶體。其生命周期由free或delete決定。在沒有釋放之前一直存在,直到程式結束。其特點是使用靈活,空間比較大,但容易出錯。

9. 指針一定要初始化為null,這樣才能用if(null != p)來判斷。

10. volatile用途:1)中斷服務程式中修改的供其它程式檢測的變量需要加volatile;2)多任務環境下各任務間共享的标志應該加volatile;3)存儲器映射的硬體寄存器通常也要加volatile說明,因為每次對它的讀寫都可能由不同意義;

 int square(volatile int *ptr)

{

   return *ptr * *ptr; 

}

volatile告訴編譯器不去優化,也就是說ptr指向的位址存的值可以在很短時間内變化,那麼你在計算乘法的過程中(想像成很多條編指令),改變了這個值,就得不到正确結果了。

static作用進一步說明:

 在c語言中,static的字面意思很容易把我們導入歧途,其實它的作用有三條。

(1)先來介紹它的第一條也是最重要的一條:隐藏。

當我們同時編譯多個檔案時,所有未加static字首的全局變量和函數都具有全局可見性

(2)static的第二個作用是保持變量内容的持久。存儲在靜态資料區的變量會在程式剛開始運作時就完成初始化,也是唯一的一次初始化。共有兩種變量存儲在靜态存儲區:全局變量和static變量,隻不過和全局變量比起來,static可以控制變量的可見範圍,說到底static還是用來隐藏的。

(3)static的第三個作用是預設初始化為0。其實全局變量也具備這一屬性,因為全局變量也存儲在靜态資料區。在靜态資料區,記憶體中所有的位元組預設值都是0x00,某些時候這一特點可以減少程式員的工作量。比如初始化一個稀疏矩陣,我們可以一個一個地把所有元素都置0,然後把不是0的幾個元素指派。如果定義成靜态的,就省去了一開始置0的操作。再比如要把一個字元數組當字元串來用,但又覺得每次在字元數組末尾加’\0’太麻煩。如果把字元串定義成靜态的,就省去 了這個麻煩,因為那裡本來就是’\0’。

繼續閱讀