C和指針 學習筆記—第3章

第三章 數據

 

1、變量的三個屬性:作用域、鏈接屬性和存儲類型(這三個屬性決定了一個變量的“可視性”(也就是它可以在什麼地方使用)和“生命期”(它的值將保持多久))。

2、char類型變量的目的是爲了讓它們容納字符型值,但字符在本質上是最小整型值;缺省的char要麼是signed char,要麼是unsigned char,這取決於編譯器。只有當char型變量顯式聲明爲signed或unsigned時,纔對它執行算術運算。

3、枚舉類型就是指它的值爲符號常量而不是字面值的類型。對於枚舉類型,如果某個符號名未顯式指定一個值,默認基礎類型爲int,默認情況下,第一個枚舉元素的值爲0,後面每個枚舉元素依次加1。

4、字符串通常存儲在字符數組中,這也是C語言麼有顯式的字符串類型的原因。如果需要修改字符串,請把它存儲於數組中

由於程序中使用字符串常量會生成一個“指向字符的常量指針”,所以當一個字符串常量出現於一個表達式中時,表達式所使用的

值就是這些字符所存儲的地址,而不是這些字符本。因此,你可以把字符串常量賦值給一個“指向字符的指針”,後者指向這些

字符所存儲的地址。但是,你不能把字符串常量賦值給一個字符數組,因爲字符串常量的直接值是一個指針,而不是這些字符身。

例如:char *message = “Hello World !”;

字符串常量Hello World!相當於一個地址,所以賦值給一個指針變量是可以的

5、typedef類型,它允許爲各種數據類型定義新名字。

typedef與宏定義的區別?

宏定義用來替代變量或者函數,放在程序的頭部,在編譯時進行變量替代,在預處理完成,它本身並不佔用編譯內存。而typedef在

編譯時處理的,而不是簡單的替換,是對類型說明符重新命名。

6、編譯器可以確認4種不同類型的作用域——文件作用域、函數作用域、代碼塊作用域和原型作用域。

代碼作用域:

位於一對花括號之間的所有語句稱爲一個代碼塊。任何在代碼塊的開始位置聲明的標識符都具有代碼塊作用域,表示它們可以被這

個代碼塊中的所有語句訪問。

當代碼塊處於嵌套狀態時,聲明與內層代碼塊的標識符的作用域到達該代碼塊的尾部便告終止。然後內層代碼塊有一個標識符的名

字與外層代碼塊的一個標識符同名,那麼內層的那個標識符就將隱藏外層的標識符——外層的那個標識符無法在內層代碼塊中通過

名字訪問。

在K&R C中,函數形參的作用域開始於形參的聲明處,位於函數體之外。

文件作用域:

任何在所有代碼塊之外聲明的標識符都具有文件作用域,它表示這些標識符從它們的聲明之處知道它在源文件結尾處都是可以訪問的。

原型作用域:

原型作用域適用於在函數原型中聲明的參數名。

函數作用域:

函數作用域只適用於語句標籤,語句標籤用於goto語句

7、當組成一個程序的各個源文件分別被編譯之後,所有的目標文件以及那些從一個或多個函數庫中引用的函數鏈接在一起,形成可執行程序。

鏈接屬性有3中——external(外部)、internal(內部)和none(無)沒有鏈接屬性的標識符(none)總是被當做單獨的個體,

也就是說該標識符的多個聲明被當做獨立不同的實體屬於internal鏈接屬性的標識符在同一個源文件內的所有聲明中都指向同一

個實體,但位於不同源文件的多個聲明則分屬不同實體。最後,屬於external鏈接屬性的標識符不論聲明多少次,位於幾個源文件

都表示同一個實體。

8、存儲類型

變量的存儲類型是指存儲變量值的內存類型;變量的存儲類型決定變量何時創建、何時銷燬、以及它的值能保持多久。

有3個地方可以存儲變量:普通內存、運行時堆棧、硬件寄存器

變量的缺省存儲類型取決於它的聲明位置:

(1)凡是在任何代碼塊之外聲明的變量總是存儲於靜態內存中,這類變量稱爲靜態變量,靜態變量在程序運行之前創建,在程序的整個執行期間始終存在

(2)在代碼塊內部聲明的變量的缺省存儲類型是自動的,也就是說它存儲於堆棧中,稱爲自動變量;在程序執行到聲明自動變量的代碼塊時,自動變量才被創建,當程序的執行流離開該代碼塊時,這些自動變量便自行銷燬。如果你反覆調用這些代碼塊,這些變量就會反覆創建和銷燬,他們存儲的位置可能與上一次存儲的位置相同,可能不同。

(3)在代碼塊內部聲明的變量,如果給它加上關鍵字static,可以使它的存儲類型從自動變爲靜態,但是修改變量的存儲類型並不表示修改該變量的作用域。

(4)關鍵字register可以用於自動變量的聲明,提示他們應該存儲於機器的硬件寄存器而不是內存中,這類變量稱爲寄存器變量。通常寄存器變量效率要比存儲於內存中的變量的訪問效率高,但是編譯器不一定將所有的register聲明的變量存儲於寄存器,可能只是選取前幾個,其餘按自動變量處理。

一旦一個變量稱爲寄存器變量,機器並不像你提供寄存器變量的地址!!

(由於寄存器值得保存和恢復,某個特定的寄存器在不同的時刻所保存的值不一定相同)

初始化:

靜態變量如果不顯式的指定其初始值,靜態變量將初始化爲0;

自動變量在鏈接時,鏈接器無法判斷自動變量的存儲位置,因爲函數的局部變量在函數的每調用都可能佔據不同的位置,基於這個理由,自動變量沒有缺省值;

因此上面原因有四個影響:

首先,是自動變量的初始化相比賦值語句效率並無提高;

其次,每次調用都會重新初始化;

再次,你可以使用任何表達式作爲初始化值;

第四,如果自動變量不初始化,它的值時不確定的

9、編譯器並不檢查對數組下標的引用是否符合數組的合法範圍內,一個良好的經驗法則是:

如果下標值時從那些已知是正確的值計算而來的,那麼無需檢查它的值,如果一個用作下標的值時根據某種方法從用戶輸入的數據產生而來的,那麼在使用它之前必須進行檢測,確保他們位於有效的範圍之內。

10、局部變量由函數內部使用,不能被其他函數通過名字引用,它在缺省的情況下的存儲類型爲自動,這是基於兩個原因:

(1)當這些變量需要時才爲它們分配存儲,這樣可以減少內存的總需求量

(2)在堆棧上爲它們分配存儲可以有效地實現遞歸

發佈了39 篇原創文章 · 獲贊 25 · 訪問量 31萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章