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

詳解C語(yǔ)言如何計(jì)算結(jié)構(gòu)體大小(結(jié)構(gòu)體的內(nèi)存對(duì)齊)

 更新時(shí)間:2023年07月21日 10:10:18   作者:可涵不會(huì)debug  
結(jié)構(gòu)體的內(nèi)存對(duì)齊是有關(guān)結(jié)構(gòu)體內(nèi)容的很重要一個(gè)知識(shí)點(diǎn),主要考察方式是計(jì)算結(jié)構(gòu)體的字節(jié)大小,所以本文就給大家詳細(xì)介紹一下C語(yǔ)言如何計(jì)算結(jié)構(gòu)體大小,文中的代碼示例介紹的非常詳細(xì),需要的朋友可以參考下

引言:

當(dāng)我們對(duì)計(jì)算結(jié)構(gòu)體一無(wú)所知,我們不妨自己思索如何計(jì)算,是不是直接計(jì)算結(jié)構(gòu)體成員變量占用內(nèi)存的大小呢?

那我們先舉個(gè)例子

struct s1
{
	int i;
	char a;
	char b;
};
struct s2
{
	char a;
	int i;
	char b;
};
int main()
{
	printf("%d\n", sizeof(struct s1));
	printf("%d\n", sizeof(struct s2));
	return 0;
}

觀察發(fā)現(xiàn)結(jié)構(gòu)體的大小計(jì)算跟我們想的很不一樣。

不應(yīng)該是兩個(gè)char類(lèi)型,一個(gè)int類(lèi)型,2*1+4答案不應(yīng)該是6嗎?

上面兩個(gè)結(jié)構(gòu)體內(nèi)容是一樣的,只有順序不一樣,為何計(jì)算結(jié)果不一樣呢?

我們就帶著以上的疑問(wèn)去探索!

一、計(jì)算偏移量

我們要研究明白結(jié)構(gòu)體的成員列表在內(nèi)存中到底是如何存儲(chǔ)的,首先要知道結(jié)構(gòu)體的各個(gè)成員變量在內(nèi)存中相較于起始位置的偏移量。這時(shí)候要引用到offsetof,這個(gè)宏可以計(jì)算結(jié)構(gòu)體成員相較于結(jié)構(gòu)體起始位置的偏移量。

使用宏offsetof

 如何使用宏offsetof?

首先有頭文件:#include<stddef.h>

參數(shù)是類(lèi)型,和成員名,返回值就是結(jié)構(gòu)體成員相較于結(jié)構(gòu)體起始位置的偏移量。

我們先試著打印下s2各個(gè)成員關(guān)于結(jié)構(gòu)體起始位置的偏移量。

發(fā)現(xiàn)結(jié)果是0、4、8,我們可以畫(huà)一張內(nèi)存圖進(jìn)行理解。

如圖所示,根據(jù)offsetof我們可以得到這樣的內(nèi)存存儲(chǔ)模式,但是這樣一共也就9個(gè)字節(jié),后面的3個(gè)字節(jié)從何而來(lái)?中間多出來(lái)的3個(gè)字節(jié)又從何而來(lái)?

我們繼續(xù)探索。

結(jié)構(gòu)體到底如何計(jì)算?

二、結(jié)構(gòu)體的對(duì)齊規(guī)則

我們經(jīng)過(guò)上面的分析,發(fā)現(xiàn)結(jié)構(gòu)體成員不是按照順序在內(nèi)存中連續(xù)存放的,而是有一定的對(duì)齊規(guī)則,接下來(lái)我們就研究結(jié)構(gòu)體的內(nèi)存規(guī)則。

  • 結(jié)構(gòu)體的第一個(gè)成員永遠(yuǎn)放在相較于結(jié)構(gòu)體變量的起始未知的偏移量為0的位置
  • 從第二個(gè)成員開(kāi)始,往后的每個(gè)成員都要對(duì)齊到某個(gè)對(duì)齊數(shù)的整數(shù)倍處。(對(duì)齊數(shù):結(jié)構(gòu)體成員自身大小和默認(rèn)對(duì)齊數(shù)的較小值)VS上默認(rèn)對(duì)齊數(shù)是8,gcc沒(méi)有默認(rèn)對(duì)齊數(shù),對(duì)齊數(shù)就是變量本身的大小。
  • 結(jié)構(gòu)體的總大小,必須是最大對(duì)齊數(shù)的整數(shù)倍,最大對(duì)齊數(shù)是:所有成員的對(duì)齊數(shù)中最大的值
  • 如果嵌套了結(jié)構(gòu)體的情況,嵌套的結(jié)構(gòu)體對(duì)齊到自己的最大對(duì)齊數(shù)的整數(shù)倍處,結(jié)構(gòu)體的整體大小就是所有最大對(duì)齊數(shù)(含嵌套結(jié)構(gòu)體的對(duì)齊數(shù))的整數(shù)倍。

三、總結(jié)計(jì)算方法

我們首先要知道結(jié)構(gòu)體變量成員的自身字節(jié)大小,然后去尋找對(duì)齊數(shù),對(duì)齊數(shù)的尋找方法就是將自身字節(jié)大小和默認(rèn)對(duì)齊數(shù)比較,取較小值,這樣先找到對(duì)齊數(shù),然后根據(jù)自身的字節(jié)大小去填充,就完成了成員在內(nèi)存中的存儲(chǔ),最后在所有的成員已經(jīng)結(jié)束存儲(chǔ),再計(jì)算最大對(duì)齊數(shù)(所有成員的對(duì)齊數(shù)中最大值),這樣就完成了計(jì)算!

我們既然已經(jīng)知道規(guī)則和計(jì)算方法,就讓我們小試牛刀一下~

四、練習(xí)

練習(xí)一:

struct s3
{
	double d;
	char c;
	int i;
};
int main()
{
	printf("%d\n", sizeof(struct s3));
	return 0;
}

上面圖片的寫(xiě)法就是左邊是本身成員變量的字節(jié)大小,右邊是默認(rèn)對(duì)齊數(shù)進(jìn)行比較,最后再?gòu)膶?duì)齊數(shù)中找出最大值,就是最大對(duì)齊數(shù),所以最后0~15就是存儲(chǔ)結(jié)構(gòu)體的大小,也就是一共16個(gè)字節(jié)

 練習(xí)二:

struct S3
{
	double d;
	char c;
	int i;
};
struct S4
{
	char c1;
	struct S3 s3;
	double d;
};
int main()
{
	printf("%d\n", sizeof(struct S4));
	return 0;
}

上面是嵌套結(jié)構(gòu)體場(chǎng)景,結(jié)構(gòu)體S3本身大小是16,需要對(duì)齊到自身最大對(duì)齊數(shù)的位置,也就是8,然后double類(lèi)型的對(duì)齊數(shù)是8,最后總字節(jié)大小也滿(mǎn)足最大對(duì)齊數(shù),所以一共32個(gè)字節(jié)。

五、為什么存在內(nèi)存對(duì)齊?

1、平臺(tái)原因

不是所有的硬件平臺(tái)都能訪(fǎng)問(wèn)任意地址上的任意數(shù)據(jù);某些平臺(tái)只能在某些地址處取某些地址處取特定類(lèi)型的數(shù)據(jù),否則拋出硬件異常

2、性能原因

數(shù)據(jù)結(jié)構(gòu)(尤其是棧)應(yīng)該盡可能在自然邊界上對(duì)齊。原因在于,為了訪(fǎng)問(wèn)未對(duì)齊的內(nèi)存,處理器需要作兩次內(nèi)存訪(fǎng)問(wèn);而對(duì)齊的內(nèi)存訪(fǎng)問(wèn)僅需要一次訪(fǎng)問(wèn)。

總體來(lái)說(shuō)

結(jié)構(gòu)體的內(nèi)存對(duì)齊,就是讓空間換時(shí)間。 

TIP:

我們?cè)谠O(shè)計(jì)結(jié)構(gòu)體時(shí),可以人為的節(jié)省空間——讓占用空間小的成員盡量集中在一起。

例如我們之前舉的例子,盡管兩個(gè)結(jié)構(gòu)體存的成員變量一樣,但是順序不一樣,結(jié)構(gòu)體內(nèi)存大小也是不同。

六、修改默認(rèn)對(duì)齊數(shù)

對(duì),你沒(méi)有聽(tīng)錯(cuò),默認(rèn)對(duì)齊數(shù)是可以修改滴,當(dāng)我們把默認(rèn)對(duì)齊數(shù)修改為1時(shí),結(jié)構(gòu)體的成員變量就是連續(xù)存儲(chǔ)的。代碼如下,計(jì)算出來(lái)的大小就是4+1+8=13

#pragma pack(1)//修改默認(rèn)對(duì)齊數(shù)為1
struct s
{
	int a;
	char b;
	double c;
};
#pragma pack()//修改默認(rèn)對(duì)齊數(shù)為默認(rèn)
int main()
{
	printf("%d\n", sizeof(struct s));
	return 0;
}

到此這篇關(guān)于詳解C語(yǔ)言如何計(jì)算結(jié)構(gòu)體大小(結(jié)構(gòu)體的內(nèi)存對(duì)齊)的文章就介紹到這了,更多相關(guān)C語(yǔ)言計(jì)算結(jié)構(gòu)體大小內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論