結構體宣告、定義及初始化
struct stu //宣告
;int main()
; //定義及初始化
return 0;
}
先說乙個熟悉的 int a;在這裡,要說明的的是struct stu是這個結構體的型別,相當於int。s1是這個結構體的變數,相當於a。
結構體成員訪問
結構體傳參
struct s
;void print1(struct s s) //傳變數
//void print2(struct s* s) //傳位址
int main()
, 1000 };
print1(s); //傳變數
// print(&s); //傳位址
return 0;
}
選擇哪個??
每次呼叫函式就要開闢一塊空間。傳值的的話,每次呼叫都要開闢乙個空間。而且,函式傳參的時候,引數是需要壓棧的。 如果傳遞乙個結構體物件的時候,結構體過大,引數壓棧的的系統開銷比較大,所以會導致效能的下降。
結構體大小(記憶體對齊)
1.記憶體對齊規則:
① 第乙個成員在與結構體變數偏移量為0的位址處。
② 其他成員變數要對齊到某個數字(對齊數)的整數倍的位址處。
③結構體總大小為最大對齊數(每個成員變數都有乙個對齊數)的整數倍。
④ 如果巢狀了結構體的情況,巢狀的結構體對齊到自己的最大對齊數的整數倍處,結構體的整體大小就是所有最大對齊數(含巢狀結構體的對齊數)的整數倍。
ps:對齊數 = 編譯器預設的乙個對齊數 與 該成員大小的較小值。
vs中預設的值為8
linux中的預設值為4
讓占用空間小的成員盡量集中在一起, 既能滿足對齊,又能節省空間。
2.例項
我把s3很拙劣的畫了出來,s4的道理也是一樣,只是要注意巢狀的結構體對齊到自己的最大對齊數的整數倍處,結構體的整體大小就是所有最大對齊數(含巢狀結構體的對齊數)的整數倍。
3.為什麼要浪費這麼多空間實現記憶體對齊呢??
① 平台原因(移植原因): 不是所有的硬體平台都能訪問任意位址上的任意資料的;某些硬體平台只能在某些位址 處取某些特定型別的資料,否則丟擲硬體異常。
② 效能原因: 資料結構(尤其是棧)應該盡可能地在自然邊界上對齊。 原因在於,為了訪問未對齊的記憶體,處理器需要作兩次記憶體訪問;而對齊的記憶體訪問僅需要一次訪問。
總體來說: 結構體的記憶體對齊是拿空間來換取時間的做法
4.那麼我們可不可以修改預設對齊數呢?
這是當然的,使用#pragma預處理命令
#include #pragma pack(1) //設定預設對齊數為1
struct s1
;#pragma pack() //取消設定的預設
int main()
這樣算下來,結構體大小就為6個位元組了。但是不要忘了取消設定的預設哦。。
位斷
1.位斷的宣告和結構體類似,有兩點不同
①位段的成員必須是 int、unsigned int 或signed int 。
②位段的成員名後邊有乙個冒號和乙個數字。
struct a ;
2.記憶體分配
① 位段的成員可以是
int unsigned int signed int
或者是
char
(屬於整形家族)型別
②位段的空間上是按照需要以4
個位元組(
int
)或者1
個位元組(
char
)的方式來開闢的。
③位段涉及很多不確定因素,位段是不跨平台的,注重可移植的程式應該避免使用位段。
3.位斷的跨平台問題
① int 位段被當成有符號數還是無符號數是不確定的。
②位段中最大位的數目不能確定。(16位機器最大16,32位機器最大32,寫成27,在16位機器會出問題。
③位段中的成員在記憶體中從左向右分配,還是從右向左分配標準尚未定義。
④ 當乙個結構包含兩個位段,第二個位段成員比較大,無法容納於第乙個位段剩餘的位時,是捨棄剩餘的位
還是利用,這是不確定的。
ps:位段在能實現功能的情況下,盡可能節省空間。
1.定義:把可能的取值一一枚舉。
enum day//星期
;int main()
以上定義的 enum day 是列舉型別。 {}中的內容是列舉型別的可能取值,也叫 列舉常量 。這些可能取值都是有值的,預設從0開始,一次遞增1。也可以在定義的時候也可以賦初值。
2.列舉優點:
① 增加**的可讀性和可維護性
② 和#define定義的識別符號比較列舉有型別檢查,更加嚴謹。
③使用方便,一次可以定義多個常量
④防止了命名汙染(封裝),define定義的是全域性變數。
⑤便於除錯 define除錯時該變數會被值替換,列舉除錯時還是它本身。
1.定義:聯合也是一種特殊的自定義型別 這種型別定義的變數也包含一系列的成員,特徵是這些成員公用同一塊空間(所以
聯合也叫共用體)。
union un
;int main()
結果並不是最大成員的大小4,而是8。因為因為聯合體存在記憶體對齊,當最大成員大小不是最大對齊數的整數倍的時候,就要對齊到最大對齊數的整數倍。
2.應用-解決大小端問題
}還有另外一種方法求大小端:
int check_sys()
else }
int main()
else
return 0;
}
完結...... 自定義型別
typedef型別 typedef 已有型別 新建型別 示例 typedef double area,volume typedef int number number i1 area a enum enum 列舉型別名 enum week 預設sun 0,可以比較 如果修改必須形如enum week...
自定義型別
下面列舉幾種c語言中常用的自定義資料型別 1.結構體型別 當描述乙個整型變數時,可以用int,描述字元型變數時,可以用char,但要描述乙個學生時,因為這個學生包含的資訊很多,比如姓名,性別,年齡等,不能通過單一的型別來描述,所以,這裡引入結構體型別,將某個事物的共有屬性集合在一起,宣告乙個結構體型...
自定義型別
列舉從字面意思理解就是將可能取的值一一枚舉出來,列舉型別沒有成員 可言,裡邊存放的是可能取值。列舉型別的定義 enum day enum color printf d n red printf d n green printf d n blue 執行結果 day和color都是定義的列舉型別,中的內...