欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C語言結(jié)構(gòu)體中內(nèi)存對齊的問題理解

 更新時間:2022年02月10日 10:56:25   作者:誠摯的喬治  
內(nèi)存對齊”應(yīng)該是編譯器的“管轄范圍”。編譯器為程序中的每個“數(shù)據(jù)單元”安排在適當(dāng)?shù)奈恢蒙?。但是C語言的一個特點就是太靈活,太強大,它允許你干預(yù)“內(nèi)存對齊”。如果你想了解更加底層的秘密,“內(nèi)存對齊”對你就不應(yīng)該再模糊了

前言

學(xué)C的同學(xué)應(yīng)該知道~

想精通C語言就不得不面對—指針與內(nèi)存

續(xù)上次指針的進階,這一章我來聊一聊C語言內(nèi)存對齊的問題

學(xué)習(xí)結(jié)構(gòu)體的你有沒有注意過結(jié)構(gòu)體向系統(tǒng)申請的內(nèi)存為多少呢的??

思考

#include<stdio.h>
typedef struct s1
{
	char a;
	char b;
	int c;
}s1;
typedef struct s2
{
	char a;
	int c;
	char b;
}s2;
int main()
{
 
	//內(nèi)存對齊的現(xiàn)象
	printf("%d\n", sizeof(s1));
	printf("%d\n", sizeof(s2));
	return 0;
}

很顯然這一段代碼就是計算s1與s2向系統(tǒng)申請的內(nèi)存大小

我:兩個char類型各為一,再加上應(yīng)該int類型的四,結(jié)果就是六

誠摯的喬治:你說的對,但不完全對,在結(jié)構(gòu)體中會出現(xiàn)內(nèi)存對齊的現(xiàn)象,不信?看結(jié)果

別慌,看到文章的最后,你(也許)就會恍然大悟

在結(jié)構(gòu)體中,內(nèi)存不是成員的大小之和

結(jié)構(gòu)體在內(nèi)存中開辟空間時內(nèi)存對齊的規(guī)則

1.結(jié)構(gòu)體中的第一個成員存放在這個結(jié)構(gòu)體的零偏移處,故第一個成員char類型的的偏移量為零

2.從第二個成員開始,每個成員都要對齊到成員對齊數(shù)的整數(shù)倍

(對齊數(shù)--成員自身大小與默認對齊數(shù)的最小值的整數(shù)倍,如果自身大小是四,默認對齊數(shù)是八,最終的對齊數(shù)就是四的倍數(shù)),一般情況下默認對齊數(shù)就是八。

3.結(jié)構(gòu)體的總大小必須是最大對齊數(shù)的整數(shù)倍 。

(最大對齊數(shù)就是每個成員對齊數(shù)中的最大值)

4.如果結(jié)構(gòu)體中嵌套結(jié)構(gòu)體的情況下,嵌套的結(jié)構(gòu)體就對齊到自己成員對齊數(shù)的最大對齊數(shù)的整數(shù)倍處,結(jié)構(gòu)體的總大小就是最大對齊數(shù)(含嵌套的結(jié)構(gòu)體成員)的整數(shù)倍。

 下面其中的一個結(jié)構(gòu)體進行分析:

 先向大家介紹一下本章的配角—offsetof

offsetof的返回值就是距離這個結(jié)構(gòu)體(自定義類型)起始位置的值

參數(shù)就是結(jié)構(gòu)體的名稱和結(jié)構(gòu)體成員的名稱。

#include<stddef.h>
#include<stdio.h>
typedef struct s
{
	char a;
	int b;
	char c;
}s;
int main()
{
	//offsetof-是指偏移量
	printf("%d\n", offsetof(s,a));
	printf("%d\n", offsetof(s,b));
	printf("%d\n", offsetof(s,c));
	return 0;
}

char a; //因為char a是結(jié)構(gòu)體第一個成員,所以偏移量就是零

int b;   //自身大小:  4    默認對齊數(shù):8   對齊數(shù):4的倍數(shù)即可,所以偏移量就是四

char c; // 自身大小: 1    默認對齊數(shù):8   對齊數(shù):1的倍數(shù)即可,所以偏移量就是八

又因為最終的結(jié)構(gòu)體大小是成員最大對齊數(shù)的倍數(shù),也就是四的倍數(shù),所以最終的結(jié)構(gòu)體的大小應(yīng)該就是十二。

到這里是不是有一定的思路了,別急,再來一道試試吧

#include<stddef.h>
#include<stdio.h>
typedef struct s
{
	double a;
	char b;
	int  c;
}s;
int main()
{
	//offsetof-是指偏移量
	printf("%d\n", offsetof(s,a));
	printf("%d\n", offsetof(s,b));
	printf("%d\n", offsetof(s,c));
	printf("%d", sizeof(s));
	return 0;
}

結(jié)果如下:

是不是跟你想的一樣呢?

同樣的,用一樣的方法進行解釋

double a;     //因為double a是結(jié)構(gòu)體第一個成員,所以偏移量就是零

char b;     //自身大?。?    默認對齊數(shù):8  對齊數(shù):1的倍數(shù)即可,所以偏移量就是八

int  c;        //自身大?。?    默認對齊數(shù):8   對齊數(shù):4的倍數(shù)即可,所以偏移量就是十二

最終結(jié)構(gòu)體的大小就是四的整數(shù)倍十六

下面給應(yīng)該結(jié)構(gòu)體嵌套結(jié)構(gòu)體的例子

#include<stdio.h>
#include<stddef.h>
typedef struct s1
{
	char i;
	char j;
	int k;
}s1;
typedef struct s2
{
	char a;
	int c;
	s1;
}s2;
int main()
{
 
	printf("%d\n", offsetof(s2, a));
	printf("%d\n", offsetof(s2, c));
	printf("%d", sizeof(s2));
	return 0;
}

我相信此時的你一定會計算結(jié)構(gòu)體想系統(tǒng)申請的大小,以及內(nèi)存對齊是咋回事

其實,內(nèi)存對齊也就那么回事兒~

為什么存在內(nèi)存對齊

知道怎樣計算后,你是否和我一樣思考

為什么內(nèi)存的申請不能想main函數(shù)中的內(nèi)存申請一樣,要多少就申請相應(yīng)大小的空間,這樣既省內(nèi)存,也不用考慮這么多。

1.平臺的原因

所謂平臺原因就是與硬件有關(guān),硬件不能訪問內(nèi)存中的每一個空間,換句話說,就是按一定的規(guī)律進行訪問,這樣內(nèi)存對齊就起到了很好的作用

2.性能的原因

數(shù)據(jù)結(jié)構(gòu)(尤其是棧),應(yīng)該盡可能的在自然邊界上對齊

因為我們的CPU訪問空間,就是一次性按四個字節(jié)的空間來訪問,內(nèi)存對齊在一定的時候避免了訪問一次的空間進行了二次訪問

如下訪問應(yīng)該int類型內(nèi)存對齊后只需要訪問一次

總的來說內(nèi)存對齊就是拿空間換取時間

當(dāng)然,我們可以實現(xiàn)內(nèi)存對齊之上,也可以進行省一定空間

就想博客開頭一道題,一模一樣的代碼,最終的結(jié)構(gòu)體的大小卻不一樣,這種就是優(yōu)化版的結(jié)構(gòu)體

這里給一個小的技巧,就是把空間小的成員盡量放在一起

到此這篇關(guān)于C語言結(jié)構(gòu)體中內(nèi)存對齊的問題理解的文章就介紹到這了,更多相關(guān)C語言 內(nèi)存對齊內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論