1. 程式人生 > >結構體記憶體對齊,位段,列舉+聯合

結構體記憶體對齊,位段,列舉+聯合

1.結構體記憶體對齊

結構體記憶體對齊規則

1.第一個成員在與結構體變數偏移量為0的地址處

2.其他成員變數要對齊到對齊數的整數倍的地址處。對齊數=編譯器預設的一個對齊數與該成員大小的 較小值

  vs中預設的值為8,linux中的預設值為4

3.結構體總大小為最大對齊數(每一個成員變數都有一個對齊數)的整數倍

4.如果嵌套了結構體的情況,巢狀結構體對齊到自己最大對齊數的整數倍處,結構體的整體大小就是所有最大對齊數

  (含巢狀結構體的對齊數)的整數倍

為什麼存在記憶體對齊?

1.平臺原因

不是所有的硬體平臺都能訪問任意地址上的任意資料的,某些硬體平臺只能在某些地址處取某些特定型別的資料

否則丟擲硬體異常

2.效能原因

資料結構(尤其是棧)應該儘可能地在自然邊界上對齊

原因在於,為了訪問未對齊的記憶體,處理器需要做兩次記憶體訪問,而記憶體對齊訪問僅需要一次訪問

總體來說

結構體的記憶體對齊是拿空間來換取時間的做法

2.結構體傳參

struct S
{
	int data[10000];
	int num;
};

struct S s = { { 1, 2, 3, 4 }, 1000 };
//結構體傳參
void print1(struct S s)
{
	printf("%d\n", s.num);
}
//結構體地址傳參
void print2(struct S* ps)
{
	printf("%d\n", ps->num);
}
int main()
{
	print1(s);
	print2(&s);
	return 0;
}

上面print1和print2函式哪個好些?

答案是首選print2函式

原因

在函式棧幀部分,我們知道函式傳參的時候,引數是需要壓棧的。如果傳遞一個結構體物件的時候,結構體過大,

引數壓棧的系統開銷比較大,所以會導致效能的下降

結論:

結構體傳參的時候,要傳結構體的地址。

3.位段

位段的宣告和結構是類似的,有兩個不同

1.位段的成員必須是int ,unsigned,int或signed int。

2.位段的成員名後邊有一個冒號和一個數字。

比如:

struct A
{
    int a:2;
    int b:5;
    int c:6;
};

A就是一個位段型別。

位段A的大小為

printf("%d\n",sizeof(struct A));

位段的記憶體分配

1.位段的成員可以是int,unsigned int,signed int 或者是char(屬於整形家族)型別。

2.位段的空間上是按照需要以4個位元組(int)或者1個位元組(char)的方式來開闢的。

3.位段涉及很多不確定的因素,位段是不跨平臺的,注意可移植的程式應該避免使用位段。

位段的跨平臺問題

1.int位段被當成有符號數還是無符號數是不確定的。

2.位段中最大位的數目不能確定(16位機器最大是16,32位機器最大是32,寫成27,在16位機器會出現問題)

3.位段中的成員在記憶體中從左向右分配,還是從右向左分配標準尚未定義

4.當一個結構包含兩個位段,第二個位段成員比較大,無法容納於第一個位段剩餘的位時,是捨棄剩餘的位還是利用,是不確定的

總結:

跟結構體相比,位段可以達到同樣的效果,但是可以很好的節省空間,但是有跨平臺的問題存在

列舉

enum Day//星期
{
	Mon,
	Tues,
	Wed,
	Thur,
	Fri,
	Sat,
	Sun
};
enum Color//顏色
{
	RED,
	GREEN,
	BLUE,
};

以上定義的enum Day,enum Color都是列舉型別

{ }中的內容是列舉型別的可能取值,也叫列舉常量。這些可能取值都是有值的,預設從0開始,一次遞增1,當然在定義的時候

也可以賦初值。

列舉的優點:

1.增加程式碼的可讀性和可維護性

2.和#define定義的標示符比較列舉有型別檢查,更加嚴謹。

3.防止了命名汙染(封裝)

4.便於除錯

5.使用方便,一次可以定義多個常量

聯合(共用體)

聯合型別的定義

聯合也是一種特殊的自定義型別

這種型別定義的變數也包含一系列的成員,特徵是這些成員公用同一塊空間(所以聯合也叫共用體)

//聯合型別的宣告
union Un
{
	char c;
	int i;
};
//聯合變數的定義
union Un un;
//計算聯合變數的大小
printf("%d\n", sizeof(un));

聯合的特點

聯合的成員是共用同一塊記憶體空間的,這樣一個聯合變數的大小,至少是最大成員的大小(因為聯合至少得有能力儲存最大的那個成員)

聯合大小的計算

1.聯合的大小至少是最大成員的大小

2.當最大成員大小不是最大對齊數的整數倍的時候,就要對齊到最大對齊數的整數倍