結構體、位段(位域)、聯合體、枚舉類型大小計算及分析

1.結構體

void test1()
{
	typedef struct
	{
		int i;
	}s;
	typedef struct 
	{
		char c1;//1
		char c2;//1
		int i;//4
	}s1;//8
	typedef struct 
	{
		char c1;//1
		int i;//4
		char c2;//1
	}s2;//12
	typedef struct 
	{
		char c2;//1
		double d;//8
		int i;//4
	}s3;//24
	typedef struct
	{
		char c1;//1
		s s;//4
		double i;//8
	}s8;//16
	typedef struct 
	{
		char c1;//1
		s1 s1;//8
		int i;//4
	}s4;//16
	typedef struct
	{
		char c1;//1
		s3 s3;//24
		int i;//4
	}s7;//40
	/*typedef struct
	{
		char c1;//1
		int i;//4
		s3 s3;//24
	}s7;//32*/
	printf("s->%d\n", sizeof(s));
	printf("s1->%d\n", sizeof(s1));
	printf("s2->%d\n", sizeof(s2));
	printf("s3->%d\n", sizeof(s3));
	printf("s4->%d\n", sizeof(s4));
	printf("s7->%d\n", sizeof(s7));
	printf("s8->%d\n", sizeof(s8));
	printf("char->%d\n", sizeof(char));//1
	printf("short->%d\n", sizeof(short));//2
	printf("int->%d\n", sizeof(int));//4
	printf("long->%d\n", sizeof(long));//4
	printf("char*->%d\n", sizeof(char*));//4
	printf("double->%d\n", sizeof(double));//8
	printf("long long->%d\n", sizeof(long long));//8

	/*typedef struct node
	{
		int data;
		 node* next;//必須加上struct,此時還沒重命名
	}node;*/
	/*typedef struct node
	{
		int data;
		struct node* next;
	}node;*/
	/*struct node
	{
		int data;
		struct node next;//不能直接包含自身,引發遞歸定義了/
	};*/
	/*typedef struct stu//(不聲明時爲匿名結構體)
	{
		int data;
	}s7;*///重命名
	//s1 s2;//重命名
	//struct stu s2;
	/* struct stu//(不聲明時爲匿名結構體)
	{
		int data;

	}s5;//定義一個自定義類型的變量
	 s5.data;*/
	 /*struct //(不聲明時爲匿名結構體)
	 {
		 int data;
	 }s6;
	 s6.data;*/
}

1.結構體是一個自定義類型,內部數據類型獨有內存空間,和聯合體(共用體要做好區分)。

2.計算機結構體大小需要內存對齊,爲什麼需要內存對齊呢?
由於32位處理器一次可以取出32個比特位(4字節),所以取數據的時候不是一個字節一個字節的取,如果數據類型小於4字節的話,會取出來然後分割,而且如果數據連續存儲,就會更加麻煩,所以引入內存對齊,以空間換時間。
在這裏插入圖片描述
3.如何進行內存對齊?
默認對齊數(win 8,linux 4)#pragma pack(n) n=1 2 4 8 16
第一位默認0開始
之後的數據要對齊,對齊數=min(默認對齊數,當前數據大小)
結構體總大小爲最大對齊數的整數倍。
嵌套了結構體的話(不能自引用,指針除外),總大小爲最大對齊數的整數倍(max(結構體,數據類型)),詳情留意s3 s4 s8,s7計算。
在這裏插入圖片描述
在這裏插入圖片描述

2.位域

void test2()
{
	struct A
	{
		int _b : 5;//4
		int _c : 4;//4
	};//4
	struct B
	{
		char _a : 3;
		char _b : 4;//1
		char _c : 5;//2
		int _d : 5;//4
	};//8
	struct C
	{
		char _a : 3;
		char _b : 4;//1
		char _c1 : 5;//2
		char _c2 : 5;//3
		char _c3 : 5;//4
		char _c4 : 5;//5
		int _d : 5;//9
	};//12
	printf("%d\n",sizeof(struct A));//4
	printf("%d\n", sizeof(struct B));//8
	printf("%d\n", sizeof(struct C));//12
}

位域是控制類型所佔的比特位。(char 不能大於8,int不能大於32),小於該類型的比特位可以拼接。
也會存在內存對齊,對齊爲最大類型的整數倍,參見B,C.

3.聯合體

void test3()
{
	union un1
	{
		char c;
		int i;
	}u1;
	union un2
	{
		char c[5];
		int i;
	}u2;
	printf("%d\n", sizeof(u1));//4
	printf("%d\n", sizeof(u2));//8
	u1.i = 1;
	if (u1.c == 1)
	{
		printf("小端機\n");
	}
	else
	{
		printf("大端機\n");
	}
	printf("%d\n", sizeof(u1));
}

聯合體成員共用一塊內存,大小爲最大數據類型,適用於不常同時出現的數據,有利於節省內存空間。
我們可以通過賦值來驗證這個,同時可以通過這個方法,來驗證大小端。
同時聯合體也會內存對齊,u2的最大爲5,但是最大對齊數爲4,所以要對齊爲8.

4.枚舉類型

void test4()
{
	enum day
	{
		HOUR,
		MINUTE,//遞推
		SECOND=5,//可以給數據大小
	};
	printf("%d\n", HOUR);
	printf("%d\n", MINUTE);
	printf("%d\n", SECOND);
}

枚舉類型常量,和宏的區別
1.可讀性好。
2.有類型檢查,安全,便於調試。
3.封裝性好,防止命名污染。
4.使用方便,可以一次定義好幾個,同時遞推數據大小,默認從0開始,也可以自己給值。

int main()
{
	//test1();//結構體
	//test2();//位段(位域)
	//test3();//聯合體共用內存空間,大小爲數據類型大的所佔的空間。
	//test4();//枚舉常量
	system("pause");
	return 0;
}

通過這個整理,我對聯合體,結構體,枚舉類型,位段有了新的理解,初學如果有錯誤,歡迎大家指正。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章