1. 程式人生 > >C語言(一 資料型別、儲存類、分配空間)

C語言(一 資料型別、儲存類、分配空間)

C語言是一種移植性強,面向過程的語言,最初由丹尼斯創立,用於編寫UNIX作業系統,移植性強指的是它的程式碼通用性強。

特點:操作簡易,結構化語言,適合處理底層事件。

我的第一個C語言程式

#include <stdio.h>  /*前處理器指令,在實際編譯之前執行的*/
int main{               /*程式主函式*/
	printf("Hello World!\n");       /*輸出*/
	return 0;
	}
	

識別符號
用來標識變數或者使用者自定義的內容,以大小寫字母或下劃線_開頭,後面加上其它字元,不含$,%,@。

資料型別
是用來標識變數型別的系統,也是用來決定變數儲存佔用的空間大小以及儲存的位模式。

資料型別
:基本型別(整數型別,浮點數型別)、列舉型別(一些只能被賦予離散整數型別的變數)、派生型別(陣列,共用體、函式、指標,結構)。可以用sizeof()來看一下這些型別儲存所佔的位元組大小。char:1位元組(8位),int和float:4位元組,double:8位元組,long double:16位元組。

float單精度浮點
1個小數點,8位指數,23位小數

double雙精度浮點
1個小數點,11位指數,52位小數

字元型常量用單引號‘a’ 、 字串用雙引號“sad”,儲存在陣列中

型別自動轉換規則
1、整型賦給浮點型:數值不變,儲存為浮點型別
2、浮點型別賦給整型,去掉小數點後數值,只儲存整數。

變數的宣告有兩種情況:

1、一種是需要建立儲存空間的。例如:int a 在宣告的時候就已經建立了儲存空間。
2、另一種是不需要建立儲存空間的,通過使用extern關鍵字宣告變數名而不定義它。 例如:extern int a 其中變數 a 可以在別的檔案中定義的。
除非有extern關鍵字,否則都是變數的定義。

extern int i; //宣告,不是定義
int i; //宣告,也是定義

C 中的左值(Lvalues)和右值(Rvalues)

1、左值:指向記憶體位置的表示式被稱為左值(lvalue)表示式。左值可以出現在賦值號的左邊或右邊。
2、右值:術語右值(rvalue)指的是儲存在記憶體中某些地址的數值。右值是不能對其進行賦值的表示式,也就是說,右值可以出現在賦值號的右邊,但不能出現在賦值號的左邊。

常量
兩種方式定義常量
const其實不是定義,而是改變一個變數的儲存類,把該變數所佔的記憶體變為只讀

#define LONG 2    //預處理
const int HANG 5   // 編譯

C語言儲存類
auto 只能在函式內使用,修飾區域性變數
register 修飾變數,可能儲存在暫存器內,取決於硬體情況
static 修飾區域性變數或者全域性變數,修飾區域性變數可以保證函式間呼叫變數的值不變,修飾全域性變數可以把作用域控制到該檔案內。
extern 儲存類用於提供一個全域性變數的引用,全域性變數對所有的程式檔案都是可見的。當您使用 ‘extern’ 時,對於無法初始化的變數,會把變數名指向一個之前定義過的儲存位置。
當您有多個檔案且定義了一個可以在其他檔案中使用的全域性變數或函式時,可以在其他檔案中使用 extern 來得到已定義的變數或函式的引用。可以這麼理解,extern 是用來在另一個檔案中宣告一個全域性變數或函式。

C 語言中全域性變數、區域性變數、靜態全域性變數、靜態區域性變數的區別
作用域看:

1、全域性變數具有全域性作用域。全域性變數只需在一個原始檔中定義,就可以作用於所有的原始檔。當然,其他不包含全域性變數定義的原始檔需要用extern 關鍵字再次宣告這個全域性變數。

2、靜態區域性變數具有區域性作用域,它只被初始化一次,自從第一次被初始化直到程式執行結束都一直存在,它和全域性變數的區別在於全域性變數對所有的函式都是可見的,而靜態區域性變數只對定義自己的函式體始終可見。

3、區域性變數也只有區域性作用域,它是自動物件(auto),它在程式執行期間不是一直存在,而是隻在函式執行期間存在,函式的一次呼叫執行結束後,變數被撤銷,其所佔用的記憶體也被收回。

4、靜態全域性變數也具有全域性作用域,它與全域性變數的區別在於如果程式包含多個檔案的話,它作用於定義它的檔案裡,不能作用到其它檔案裡,即被static關鍵字修飾過的變數具有檔案作用域。這樣即使兩個不同的原始檔都定義了相同名字的靜態全域性變數,它們也是不同的變數。

分配記憶體空間看:

1、全域性變數,靜態區域性變數,靜態全域性變數都在靜態儲存區分配空間,而區域性變數在棧裡分配空間

2、全域性變數本身就是靜態儲存方式, 靜態全域性變數當然也是靜態儲存方式。這兩者在儲存方式上並無不同。這兩者的區別雖在於非靜態全域性變數的作用域是整個源程式,當一個源程式由多個原始檔組成時,非靜態的全域性變數在各個原始檔中都是有效的。而靜態全域性變數則限制了其作用域,即只在定義該變數的原始檔內有效,在同一源程式的其它原始檔中不能使用它。由於靜態全域性變數的作用域侷限於一個原始檔內,只能為該原始檔內的函式公用,因此可以避免在其它原始檔中引起錯誤。

1)靜態變數會被放在程式的靜態資料儲存區(全域性可見)中,這樣可以在下一次呼叫的時候還可以保持原來的賦值。這一點是它與堆疊變數和堆變數的區別。
2)變數用static告知編譯器,自己僅僅在變數的作用範圍內可見。這一點是它與全域性變數的區別。
從以上分析可以看出, 把區域性變數改變為靜態變數後是改變了它的儲存方式即改變了它的生存期。把全域性變數改變為靜態變數後是改變了它的作用域,限制了它的使用範圍。因此static 這個說明符在不同的地方所起的作用是不同的。應予以注意。

Tips:

A.若全域性變數僅在單個C檔案中訪問,則可以將這個變數修改為靜態全域性變數,以降低模組間的耦合度;
B.若全域性變數僅由單個函式訪問,則可以將這個變數改為該函式的靜態區域性變數,以降低模組間的耦合度;
C.設計和使用訪問動態全域性變數、靜態全域性變數、靜態區域性變數的函式時,需要考慮重入問題,因為他們都放在靜態資料儲存區,全域性可見;
D.如果我們需要一個可重入的函式,那麼,我們一定要避免函式中使用static變數(這樣的函式被稱為:帶"內部儲存器"功能的的函式)
E.函式中必須要使用static變數情況:比如當某函式的返回值為指標型別時,則必須是static的區域性變數的地址作為返回值,若為auto型別,則返回為錯指標。