C語(yǔ)言結(jié)構(gòu)體內(nèi)存對(duì)齊和offsetof宏、container-創(chuàng)新互聯(lián)

1.結(jié)構(gòu)體變量中的元素如何訪問(wèn)

(1)數(shù)組中元素的訪問(wèn)方式:表面上有2種方式(數(shù)組下標(biāo)方式和指針?lè)绞剑?;?shí)質(zhì)上都是指針?lè)绞皆L問(wèn)。
(2)結(jié)構(gòu)體變量中的元素訪問(wèn)方式:只有一種,用.或者->的方式來(lái)訪問(wèn)。
(C語(yǔ)言規(guī)定用結(jié)構(gòu)體變量來(lái)訪問(wèn)元素用. 用結(jié)構(gòu)體變量的指針來(lái)訪問(wèn)元素用->。)

創(chuàng)新互聯(lián)長(zhǎng)期為上千家客戶提供的網(wǎng)站建設(shè)服務(wù),團(tuán)隊(duì)從業(yè)經(jīng)驗(yàn)10年,關(guān)注不同地域、不同群體,并針對(duì)不同對(duì)象提供差異化的產(chǎn)品和服務(wù);打造開(kāi)放共贏平臺(tái),與合作伙伴共同營(yíng)造健康的互聯(lián)網(wǎng)生態(tài)環(huán)境。為濱海企業(yè)提供專業(yè)的網(wǎng)站制作、成都網(wǎng)站設(shè)計(jì),濱海網(wǎng)站改版等技術(shù)服務(wù)。擁有10余年豐富建站經(jīng)驗(yàn)和眾多成功案例,為您定制開(kāi)發(fā)。2.結(jié)構(gòu)體的對(duì)齊訪問(wèn)

總結(jié)下:結(jié)構(gòu)體對(duì)齊的分析要點(diǎn)和關(guān)鍵:
1、結(jié)構(gòu)體對(duì)齊要考慮:結(jié)構(gòu)體整體本身必須安置在4字節(jié)對(duì)齊處,結(jié)構(gòu)體對(duì)齊后的大小必須4的倍數(shù)(編譯器設(shè)置為4字節(jié)對(duì)齊時(shí),如果編譯器設(shè)置為8字節(jié)對(duì)齊,則這里的4是8)
2、結(jié)構(gòu)體中每個(gè)元素本身都必須對(duì)其存放,而每個(gè)元素本身都有自己的對(duì)齊規(guī)則。
3、編譯器考慮結(jié)構(gòu)體存放時(shí),以滿足以上2點(diǎn)要求的最少內(nèi)存需要的排布來(lái)算。

gcc支持但不推薦的對(duì)齊指令:#pragma pack() #pragma pack(n) (n=1/2/4/8)

我們需要#prgama pack(n)開(kāi)頭,以#pragma pack()結(jié)尾,定義一個(gè)區(qū)間,這個(gè)區(qū)間內(nèi)的對(duì)齊參數(shù)就是n。

#pragma pack(1)
struct mystruct
{short d;
	int b;
	char a;
};
#pragma pack()
gcc推薦的對(duì)齊指令__attribute__((packed)) attribute((aligned(n)))

(1)__attribute__((packed))使用時(shí)直接放在要進(jìn)行內(nèi)存對(duì)齊的類型定義的后面,然后它起作用的范圍只有加了這個(gè)東西的這一個(gè)類型。packed的作用就是取消對(duì)齊訪問(wèn)。

struct mystruct
{short d;
	int b;
	char a;
}__attribute__((packed));

(2)__attribute__((aligned(n)))使用時(shí)直接放在要進(jìn)行內(nèi)存對(duì)齊的類型定義的后面,然后它起作用的范圍只有加了這個(gè)東西的這一個(gè)類型。它的作用是讓整個(gè)結(jié)構(gòu)體變量整體進(jìn)行n字節(jié)對(duì)齊(注意是結(jié)構(gòu)體變量整體n字節(jié)對(duì)齊,而不是結(jié)構(gòu)體內(nèi)各元素也要n字節(jié)對(duì)齊)

struct mystruct
{short d;
	int b;
	char a;
}__attribute__((aligned(16)));

參考閱讀blog:
結(jié)構(gòu)體字節(jié)對(duì)齊參考博客

GCC___attribute__關(guān)鍵字和字節(jié)對(duì)齊

3.offsetof宏

(1)offsetof宏的作用是:用宏來(lái)計(jì)算結(jié)構(gòu)體中某個(gè)元素和結(jié)構(gòu)體首地址的偏移量(其實(shí)質(zhì)是通過(guò)編譯器來(lái)幫我們計(jì)算)。
(2)offsetof宏的原理:我們虛擬一個(gè)type類型結(jié)構(gòu)體變量,然后用type.member的方式來(lái)訪問(wèn)那個(gè)member元素,繼而得到member相對(duì)于整個(gè)變量首地址的偏移量。

// TYPE是結(jié)構(gòu)體類型,MEMBER是結(jié)構(gòu)體中一個(gè)元素的元素名
// 這個(gè)宏返回的是member元素相對(duì)于整個(gè)結(jié)構(gòu)體變量的首地址的偏移量,類型是int
#define offsetof(TYPE, MEMBER) ((int) &((TYPE *)0)->MEMBER)

(TYPE *)0這是一個(gè)強(qiáng)制類型轉(zhuǎn)換,把0地址強(qiáng)制類型轉(zhuǎn)換成一個(gè)指針,這個(gè)指針指向一個(gè)TYPE類型的結(jié)構(gòu)體變量。 (實(shí)際上這個(gè)結(jié)構(gòu)體變量可能不存在,但是只要我不去解引用這個(gè)指針就不會(huì)出錯(cuò))。
((TYPE *)0)->MEMBER (TYPE *)0是一個(gè)TYPE類型結(jié)構(gòu)體變量的指針,通過(guò)指針指針來(lái)訪問(wèn)這個(gè)結(jié)構(gòu)體變量的member元素

&((TYPE *)0)->MEMBER等效于&(((TYPE *)0)->MEMBER),意義就是得到member元素的地址。但是因?yàn)檎麄€(gè)結(jié)構(gòu)體變量的首地址是0,

4.container_of宏
// TYPE是結(jié)構(gòu)體類型,MEMBER是結(jié)構(gòu)體中一個(gè)元素的元素名
// 這個(gè)宏返回的是member元素相對(duì)于整個(gè)結(jié)構(gòu)體變量的首地址的偏移量,類型是int
#define offsetof(TYPE, MEMBER) ((int) &((TYPE *)0)->MEMBER)

// ptr是指向結(jié)構(gòu)體元素member的指針,type是結(jié)構(gòu)體類型,member是結(jié)構(gòu)體中一個(gè)元素的元素名
// 這個(gè)宏返回的就是指向整個(gè)結(jié)構(gòu)體變量的指針,類型是(type *)
#define container_of(ptr, type, member) ({	\
	const typeof(((type *)0)->member) * __mptr = (ptr);	\
	(type *)((char *)__mptr - offsetof(type, member)); })

(1)作用:知道一個(gè)結(jié)構(gòu)體中某個(gè)元素的指針,反推這個(gè)結(jié)構(gòu)體變量的指針。有了container_of宏,我們可以從一個(gè)元素的指針得到整個(gè)結(jié)構(gòu)體變量的指針,繼而得到結(jié)構(gòu)體中其他元素的指針。
(2)typeof關(guān)鍵字的作用是:typepef(a)時(shí)由變量a得到a的類型,typeof就是由變量名得到變量數(shù)據(jù)類型的。
(3)這個(gè)宏的工作原理:先用typeof得到member元素的類型定義成一個(gè)指針,然后用這個(gè)指針減去該元素相對(duì)于整個(gè)結(jié)構(gòu)體變量的偏移量(偏移量用offsetof宏得到的),減去之后得到的就是整個(gè)結(jié)構(gòu)體變量的首地址了,再把這個(gè)地址強(qiáng)制類型轉(zhuǎn)換為type *即可。

struct mystruct
{short d;
	int b;
	char a;
};

int main(void)
{struct mystruct s1;
	struct mystruct *ps = NULL;
	int *p = &(s1.a);
	
	printf("s1 = %p.\n", &s1);
	
	ps = container_of(p, struct mystruct, a);
	
	printf("ps = %p.\n", ps);
	
	return 0;
}

知道一個(gè)結(jié)構(gòu)體中a元素的指針,反推這個(gè)結(jié)構(gòu)體變量的指針。
結(jié)果為:
s1 = 0x7ffd8cd5d2fc. ps = 0x7ffd8cd5d2fc.

你是否還在尋找穩(wěn)定的海外服務(wù)器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機(jī)房具備T級(jí)流量清洗系統(tǒng)配攻擊溯源,準(zhǔn)確流量調(diào)度確保服務(wù)器高可用性,企業(yè)級(jí)服務(wù)器適合批量采購(gòu),新人活動(dòng)首月15元起,快前往官網(wǎng)查看詳情吧

網(wǎng)頁(yè)標(biāo)題:C語(yǔ)言結(jié)構(gòu)體內(nèi)存對(duì)齊和offsetof宏、container-創(chuàng)新互聯(lián)
當(dāng)前地址:http://bm7419.com/article22/cedgjc.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供手機(jī)網(wǎng)站建設(shè)服務(wù)器托管、網(wǎng)站策劃、網(wǎng)站設(shè)計(jì)ChatGPT、網(wǎng)站改版

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

搜索引擎優(yōu)化