1、結構體(struct)
結構體型別宣告、定義結構體型別變數以及結構體變數的使用
#include #include // struct 是乙個c語言的乙個關鍵字,用來宣告乙個結構體型別
// 宣告了乙個名字叫 student 的結構體型別
// 有兩個成員,分別是整型的 id(學號) 字元陣列 name(名字)
// struct 只是宣告了這樣一種資料型別,和普通的資料型別比如int、char
// 一樣本身是沒有分配空間的,只有在定義變數的時候才會為變數分配空間
struct student
; //用struct 宣告型別的時候要有 ;號,和函式相區分
#if 0
// 變數定義2:直接在結構型別宣告的時候定義變數
struct teacher
t1,t2; // 定義了兩個老師的變數 變數名叫 t1、t2
// 變數定義3:結構型別可以不要名字,也就是說不能在其他地方使用了
// 只能在型別宣告的時候定義變數
struct
a, b; // 定義結構體變數a和b
// int main()
#endif
// 結構體變數的初始化和成員使用
int main1();
struct student stu2 = ;
// 結構的成員變數的使用,結構變數使用成員變數,需要點 . 指明使用的是哪乙個成員
printf ("id = %d, name = %s\n", stu.id, stu.name); }
int main()
結構體的記憶體對齊模式
資料項只能儲存在位址是資料項大小的整數倍的記憶體位置上,
例如 int 型別占用4個位元組,位址只能在0,4,8等位置上。
每 個作業系統都有自己的預設記憶體對齊係數,如果是新版本的作業系統,預設對齊係數一般都是8,因為作業系統定義的最大型別儲存單元就是8個位元組,例如 long long,不存在超過8個位元組的型別(例如int是4,char是1,long在32位編譯時是4,64位編譯時是 8)。當作業系統的預設對齊係數與記憶體對齊的理論產生衝突時,以作業系統的對齊係數為基準。例如:假設作業系統的預設對齊係數是4,那麼對與long long這個型別的變數就不滿足第一節所說的,也就是說long long這種結構,可以儲存在被4整除的位置上,也可以儲存在被8整除的位置上。可以通過#pragma pack()語句修改作業系統的預設對齊係數,編寫程式的時候不建議修改預設對齊係數。
防止出現二次訪問,提高效率但是損耗了空間。
結構體的位域:位欄位
有些資料在儲存時並不需要占用乙個完整的位元組,只需要占用乙個或幾個二進位制位即可。例如開關只有通電和斷電兩種狀態,用 0 和 1 表示足以,也就是用乙個二進位。正是基於這種考慮,c語言又提供了一種叫做位域的資料結構。
位域的具體儲存規則
當相鄰成員的型別相同時,如果它們的位寬之和小於型別的 sizeof 大小,那麼後面的成員緊鄰前乙個成員儲存,直到不能容納為止;如果它們的位寬之和大於型別的 sizeof 大小,那麼後面的成員將從新的儲存單元開始,其偏移量為型別大小的整數倍。
當相鄰成員的型別不同時,不同的編譯器有不同的實現方案,gcc 會壓縮儲存,而 vc/vs 不會。
無名位域一般用來作填充或者調整成員位置。因為沒有名稱,無名位域不能使用。
結構體陣列
結構體巢狀
結構體指標
#include #include struct student
;int main1()
void printa(struct student a)
void printb(struct student *a)
int main()
; struct student b;
b = a;// 結構體變數之間可以直接賦值
// 結構體變數之間可以直接賦值導致結構變數可以直接作為函式引數進行傳遞
printb(&b);
printf ("id = %d, name = %s\n", b.id, b.name);
return 0;
}
2、共用體(union)
結構體和共用體的區別在於:結構體的各個成員會占用不同的記憶體,互相之間沒有影響;而共用體的所有成員占用同一段記憶體,修改乙個成員會影響其餘所有成員。
結構體占用的記憶體大於等於所有成員占用的記憶體的總和(成員之間可能會存在縫隙),共用體占用的記憶體等於最長的成員占用的記憶體。共用體使用了記憶體覆蓋技術,同一時刻只能儲存乙個成員的值,如果對新的成員賦值,就會把原來成員的值覆蓋掉。
共用體的所有成員起始位址的是一樣的。
判斷大小端儲存方式
#include // 小端返回真(1),大端返回假(0)
int islittleendian()a;
a.a = 1;
return (a.ch == 1);
}int main()
3、列舉(enum)
#include // enum 是c語言的乙個關鍵字,用來宣告列舉型別
enum week;
int main()
4、extern
extern可置於變數或者函式前,以表示變數或者函式的定義在別的檔案中,提示編譯器遇到此變數或函式時,在其它模組中尋找其定義。
5、static
在區域性靜態變數前面加上關鍵字static,該區域性變數便成了靜態區域性變數。靜態區域性變數有以下特點:
(1)該變數在全域性資料區分配記憶體
(2)如果不顯示初始化,那麼將被隱式初始化為0
(3)它始終駐留在全域性資料區,直到程式執行結束
(4)其作用域為區域性作用域,當定義它的函式或語句塊結束時,其作用域隨之結束。
在全域性變數前面加上關鍵字static,該全域性變數變成了全域性靜態變數。
全域性靜態變數有以下特點:
(1)在全域性資料區內分配記憶體
(2)如果沒有初始化,其預設值為0
(3)該變數在本檔案內從定義開始到檔案結束可見,即只能在本檔案內使用
在函式的返回型別加上static關鍵字,函式即被定義成靜態函式。
靜態函式有以下特點:
(1) 靜態函式只能在本原始檔中使用
(2) 在檔案作用域中宣告的inline函式預設為static
說明:靜態函式只是乙個普通的全域性函式,只不過受static限制,他只能在所在檔案內使用,不能在其他檔案內使用。
6、const
const int * p; // p可變,p指向的物件不可變
int const * p; // p可變,p指向的物件不可變
int * const p; // p不可變,p指向的物件可變
const int * const p; // 指標p和p指向的物件都不可變
這裡給出乙個記憶和理解的方法:
先忽略型別名(編譯器解析的時候也是忽略型別名),我們看const離哪個近,「近水樓台先得月」,離誰近就修飾誰。
const (int) *p //const 修飾*p,p是指標,*p是指標指向的物件,不可變。
(int) const * p; //const 修飾*p,p是指標,*p是指標指向的物件,不可變。
( int) * const p;//const 修飾p,p不可變,p指向的物件可變
const ( int)* const p; // 前乙個const修飾*p,後乙個const修飾p,指標p和p指向的物件都不可變
關於復合型別的學習
一 指標和引用 1.指標 型別 指標變數 例如 int pi 簡單的使用方法 int ival 120 int pi ival 注意 定義指標時指定的型別實際上是指標指向的物件的型別 通過指標可以直接給物件賦值 定義指標時必需給指標初始化。初始化指標的方法 int pi nullptr int pi...
C 學習 C 復合型別
1.引用 引用是為某乙個變數起了另乙個名字,定義方式為type rval val 引用型別必須與引用的變數型別完全一致,引用後,rval和val將會被視為乙個變數,只不過有兩種呼叫方式,改變rval的值,val的值會隨之改變,改變val的值,對rval進行呼叫時值也發生了改變。將乙個值繫結後,將無法...
復合型別 盤點 複合材料常見的結構芯材型別及特點
複合材料工業中,使用相對較薄 結實的面板粘結到較厚 輕質的芯材上的想法,使該行業能夠構建結實 堅固 輕便且高度耐用的結構。常見的粘合夾層結構是玻璃纖維和碳纖維板。這項技術已在船 卡車 汽車 風力渦輪機葉片和建築結構中得到證明。如何正確選擇芯層和表層,重量增加3 可使抗彎強度和剛度分別提高3.5倍和7...