亚洲精品久久久久久久久久久,亚洲国产精品一区二区制服,亚洲精品午夜精品,国产成人精品综合在线观看,最近2019中文字幕一页二页

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

解析C語(yǔ)言結(jié)構(gòu)體字節(jié)如何對(duì)齊

電子工程師 ? 來(lái)源:編程學(xué)習(xí)總站 ? 作者:寫(xiě)代碼的牛頓 ? 2021-06-12 17:42 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

01

默認(rèn)字節(jié)對(duì)齊

C語(yǔ)言結(jié)構(gòu)體字節(jié)對(duì)齊是老生常談的問(wèn)題了,也是高頻面試題,現(xiàn)在我們來(lái)深入研究這個(gè)問(wèn)題,徹底弄懂到底是怎么回事,給你一個(gè)結(jié)構(gòu)體定義和平臺(tái)機(jī)器位數(shù)就能手動(dòng)計(jì)算出結(jié)構(gòu)體占用字節(jié)數(shù),現(xiàn)在我們不使用宏#pragma pack,采用默認(rèn)字節(jié)對(duì)齊方式。

先拋出結(jié)論:

在一個(gè)結(jié)構(gòu)體中第一個(gè)成員變量放在偏移為0的位置,以后的變量都存儲(chǔ)在該變量占用字節(jié)數(shù)整數(shù)倍的地址上。

結(jié)構(gòu)體總大小,必須是內(nèi)部最大成員變量的整數(shù)倍,不足的補(bǔ)齊。

好了,現(xiàn)在我們直接寫(xiě)個(gè)小程序驗(yàn)證并分析是否真是這樣一回事。

struct st{ short a1; short a2; short a3; }; struct st2{ long a1; short a2; };

這里我們定義了兩個(gè)很簡(jiǎn)單的結(jié)構(gòu)體,short占用2個(gè)字節(jié),struct st我們一眼就知道大小了6個(gè)字節(jié),但是struct st2呢?筆者電腦是64位,那么long占用8個(gè)字節(jié),short占用2個(gè)字節(jié)。我們先來(lái)按照結(jié)論進(jìn)行分析,在struct st2中成員變量a1在偏移0處存儲(chǔ)且占用8個(gè)字節(jié),成員變量a2占用2個(gè)字節(jié),由于8是2的倍數(shù),所以a2在偏移8的位置存儲(chǔ),又因?yàn)橛薪Y(jié)論2。

我們根據(jù)結(jié)論2可以得出,struct st2必須占用8的倍數(shù)大小,所以struct st2總大小是16個(gè)字節(jié),不足的后面補(bǔ)齊。現(xiàn)在我分別打印出struct st1和struct st2占用字節(jié)數(shù)大小和struct st2各個(gè)成員變量地址,觀察是否和分析的一樣。

int main() { struct st2 st_val2; printf(“sizeof(long) = %d ”, sizeof(long)); printf(“sizeof(struct st) = %d ”, sizeof(struct st)); printf(“sizeof(struct st2) = %d ”, sizeof(struct st2)); printf(“st_val2 addr = %p ”, &st_val2); printf(“st_val2 a1 addr = %p ”, &st_val2.a1); printf(“st_val2 a2 addr = %p ”, &st_val2.a2); return 0; }

編譯運(yùn)行輸出:

sizeof(long) = 8 sizeof(struct st) = 6 sizeof(struct st2) = 16 st_val2 addr = 0x7ffee107f3b8 st_val2 a1 addr = 0x7ffee107f3b8 st_val2 a2 addr = 0x7ffee107f3c0

現(xiàn)在我們看一下輸出結(jié)果,struct st如我們所愿占用6個(gè)字節(jié)大小,struct st2也按照我們分析的一樣占用16個(gè)字節(jié)。我們?cè)诔绦蛑卸x了一個(gè)struct st2類(lèi)型變量st_val2,從輸出中可以看出變量st_val2的a1成員變量和st_val2變量地址一樣,成員變量a2在偏移8處存儲(chǔ)(0x c0 = 0xb8 + 8)。一切如我們所愿,看起來(lái)好像挺簡(jiǎn)單的,我們知道C語(yǔ)言有豐富的數(shù)據(jù)類(lèi)型,下面我們?cè)俣x一個(gè)更復(fù)雜的結(jié)構(gòu)體。

struct st3{ int a1; char a2; short a3; long a4; char a5; };

這個(gè)結(jié)構(gòu)體包含了大量數(shù)據(jù)類(lèi)型成員變量,再?gòu)?fù)雜的結(jié)構(gòu)體也能按照我們的結(jié)論分析到底占用了幾個(gè)字節(jié)。

在struct st3中int型成員變量a1占用4個(gè)字節(jié),在偏移0處存儲(chǔ),char型成員變量a2占用2個(gè)字節(jié)那么應(yīng)該放在2的倍數(shù)地址處存儲(chǔ),a1已經(jīng)占用了4個(gè)字節(jié),所以a2應(yīng)該在偏移4的地址存儲(chǔ)。

short型成員變量a3占用2個(gè)字節(jié),也應(yīng)該放在2的倍數(shù)地址處存儲(chǔ),所以a3在偏移6的地址處存儲(chǔ),a2后面填充1個(gè)字節(jié)。

long型成員變量a4占用8個(gè)字節(jié),應(yīng)該放在8的倍數(shù)地址上存儲(chǔ),前面我們已經(jīng)知道a3在偏移6的地址處存儲(chǔ),且占用2個(gè)字節(jié)8 = 6 + 2,所以a4應(yīng)該在偏移8的地址處存儲(chǔ)。

最后一個(gè)char型成員變量a5占用一個(gè)字節(jié),那么a5在偏移16地址處存儲(chǔ)。

現(xiàn)在我們計(jì)算一下struct st3結(jié)構(gòu)體占用空間大小,從a5偏移出計(jì)算16 + 1 = 17。在struct st3中最大成員變量占用8個(gè)字節(jié),所以結(jié)構(gòu)體總大小應(yīng)該是8的倍數(shù),最后結(jié)構(gòu)體總大小是17 + 7 = 24,這里的7個(gè)字節(jié)在最后補(bǔ)齊。

我們依舊寫(xiě)一個(gè)小程序輸出struct st3類(lèi)型變量各個(gè)成員變量地址和結(jié)構(gòu)體總大小。

int main() { struct st3 st_val3; printf(“sizeof(struct st3) = %d ”, sizeof(struct st3)); printf(“st_val3 addr = %p ”, &st_val3); printf(“st_val3.a1 addr = %p ”, &st_val3.a1); printf(“st_val3.a2 addr = %p ”, &st_val3.a2); printf(“st_val3.a3 addr = %p ”, &st_val3.a3); printf(“st_val3.a4 addr = %p ”, &st_val3.a4); printf(“st_val3.a5 addr = %p ”, &st_val3.a5); return 0; }

編譯運(yùn)行輸出:

sizeof(struct st3) = 24 st_val3 addr = 0x7ffeed0c33b0 st_val3.a1 addr = 0x7ffeed0c33b0 st_val3.a2 addr = 0x7ffeed0c33b4 st_val3.a3 addr = 0x7ffeed0c33b6 st_val3.a4 addr = 0x7ffeed0c33b8 st_val3.a5 addr = 0x7ffeed0c33c0

從輸出我們可以看出,和我們分析的完全一樣。

枚舉類(lèi)型變量和聯(lián)合體類(lèi)型變量都可以作為結(jié)構(gòu)體的成員變量,在分析這些結(jié)構(gòu)體占用大小時(shí),分析方法和我們上面的一模一樣,只需要把內(nèi)部任何一種數(shù)據(jù)類(lèi)型變量當(dāng)做一個(gè)普通變量看待即可,但是結(jié)構(gòu)體類(lèi)型成員變量有點(diǎn)不一樣,它不適用于結(jié)論2,我們舉個(gè)例子。

struct st4{ char a1[3]; int a2; long a3; struct st3 a4; };

在struct st4中我們定義了一個(gè)struct st3類(lèi)型成員變量,前面我們已經(jīng)分析過(guò)了struct st3占用24個(gè)字節(jié)。成員變量a1占用3個(gè)字節(jié),成員變量a2占用4個(gè)字節(jié),所以a2存儲(chǔ)在偏移4的地址上,在a1后面填充一個(gè)字節(jié)。成員變量a3占用8個(gè)字節(jié),則a3存儲(chǔ)在偏移8的地址上。那么結(jié)構(gòu)體總共占用字節(jié)數(shù)大小是:8 + 8 + 24 = 40。

最后我們寫(xiě)一個(gè)程序驗(yàn)證一下是否如此。

int main() { struct st4 st_val4; printf(“sizeof(struct st4) = %d ”, sizeof(struct st4)); printf(“st4 addr = %p ”, &st_val4); printf(“st_val4.a1 addr = %p ”, &st_val4.a1); printf(“st_val4.a2 addr = %p ”, &st_val4.a2); printf(“st_val4.a3 addr = %p ”, &st_val4.a3); printf(“st_val4.a4 addr = %p ”, &st_val4.a4); return 0; }

編譯運(yùn)行輸出:

sizeof(struct st4) = 40 st4 addr = 0x7ffeec1263a0 st_val4.a1 addr = 0x7ffeec1263a0 st_val4.a2 addr = 0x7ffeec1263a4 st_val4.a3 addr = 0x7ffeec1263a8 st_val4.a4 addr = 0x7ffeec1263b0

和我們分析的一模一樣。

02

#pragma pack宏的作用

我們看一下下面這段代碼。

#pagma pack(1)int main() { struct st3 st_val3; printf(“sizeof(struct st3) = %d ”, sizeof(struct st3)); printf(“st_val3 addr = %p ”, &st_val3); printf(“st_val3.a1 addr = %p ”, &st_val3.a1); printf(“st_val3.a2 addr = %p ”, &st_val3.a2); printf(“st_val3.a3 addr = %p ”, &st_val3.a3); printf(“st_val3.a4 addr = %p ”, &st_val3.a4); printf(“st_val3.a5 addr = %p ”, &st_val3.a5); return 0; }

這段代碼里我們使用了#pagma pack宏,表示結(jié)構(gòu)體按1字節(jié)對(duì)齊。也就是說(shuō)結(jié)構(gòu)體變量st_val3總大小是內(nèi)部成員變量占用字節(jié)數(shù)總和,沒(méi)有字節(jié)填充。

現(xiàn)在編譯運(yùn)行如下:

sizeof(struct st3) = 16 st_val3 addr = 0x7ffee13a93b8 st_val3.a1 addr = 0x7ffee13a93b8 st_val3.a2 addr = 0x7ffee13a93bc st_val3.a3 addr = 0x7ffee13a93bd st_val3.a4 addr = 0x7ffee13a93bf st_val3.a5 addr = 0x7ffee13a93c7

在struct st3中int型a1占用4字節(jié),char型變量a2占用1個(gè)字節(jié),short型變量a3占用2個(gè)字節(jié),long型變量a4占用8個(gè)字節(jié),char型變量a5占用1個(gè)字節(jié),所以總大小是:4 + 1 + 2 + 8 + 1 = 16。如果是#pagma pack(2)呢?相信你可以自己計(jì)算了。

編輯:jq

聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • C語(yǔ)言
    +關(guān)注

    關(guān)注

    183

    文章

    7636

    瀏覽量

    144294
  • 代碼
    +關(guān)注

    關(guān)注

    30

    文章

    4930

    瀏覽量

    72802

原文標(biāo)題:C語(yǔ)言結(jié)構(gòu)體字節(jié)對(duì)齊

文章出處:【微信號(hào):AndroidPush,微信公眾號(hào):Android編程精選】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評(píng)論

    相關(guān)推薦
    熱點(diǎn)推薦

    MDK uVision V5.36.00使用rt_packed進(jìn)行字節(jié)對(duì)齊,但無(wú)效,為什么?

    各位RTT專(zhuān)家好: MDK uVision V5.36.00使用rt_packed進(jìn)行字節(jié)對(duì)齊,但無(wú)效。
    發(fā)表于 09-24 06:37

    定義IO初始化結(jié)構(gòu)

    由上述IOPORT相關(guān)功能的枚舉類(lèi)型我們可以知道,在對(duì)IOPORT模塊進(jìn)行初始化時(shí)需要根據(jù)情況配置它們。因此我們定義一個(gè)IOPORT初始化的結(jié)構(gòu)類(lèi)型IOPORT_Init_t,它的成員包括了由上述所有枚舉類(lèi)型所聲明的變量,因此該結(jié)構(gòu)
    的頭像 發(fā)表于 07-16 16:26 ?1020次閱讀

    《ESP32S3 Arduino開(kāi)發(fā)指南》第三章 C/C++語(yǔ)言基礎(chǔ)

    ++基礎(chǔ),由于篇幅有限,在此僅對(duì)C/C++語(yǔ)言基礎(chǔ)進(jìn)行簡(jiǎn)單介紹。本章將分為如下9個(gè)小節(jié):3.1 數(shù)據(jù)類(lèi)型3.2 運(yùn)算符3.3 表達(dá)式3.4 數(shù)組3.5 字符串3.6 注釋3.7 順序結(jié)構(gòu)
    發(fā)表于 06-10 09:20

    程序設(shè)計(jì)與數(shù)據(jù)結(jié)構(gòu)

    《程序設(shè)計(jì)與數(shù)據(jù)結(jié)構(gòu)》重點(diǎn)闡述了三大方向內(nèi)容: 1. C語(yǔ)言學(xué)習(xí)中的痛點(diǎn):針對(duì)當(dāng)前工程師在C語(yǔ)言學(xué)習(xí)中的痛點(diǎn),如指針函數(shù)與函數(shù)指針,如何靈
    發(fā)表于 05-13 16:45

    深入理解C語(yǔ)言C語(yǔ)言循環(huán)控制

    C語(yǔ)言編程中,循環(huán)結(jié)構(gòu)是至關(guān)重要的,它可以讓程序重復(fù)執(zhí)行特定的代碼塊,從而提高編程效率。然而,為了避免程序進(jìn)入無(wú)限循環(huán),C語(yǔ)言提供了多種循
    的頭像 發(fā)表于 04-29 18:49 ?1581次閱讀
    深入理解<b class='flag-5'>C</b><b class='flag-5'>語(yǔ)言</b>:<b class='flag-5'>C</b><b class='flag-5'>語(yǔ)言</b>循環(huán)控制

    C語(yǔ)言結(jié)構(gòu)與聯(lián)合體的深度解析:內(nèi)存布局與應(yīng)用場(chǎng)景

    一、基礎(chǔ)概念與核心差異 1.1 結(jié)構(gòu)(Struct)的本質(zhì) **結(jié)構(gòu)C語(yǔ)言中實(shí)現(xiàn)數(shù)據(jù)封裝的
    發(fā)表于 04-08 09:18

    ?VLM(視覺(jué)語(yǔ)言模型)?詳細(xì)解析

    的詳細(xì)解析: 1. 核心組成與工作原理 視覺(jué)編碼器 :提取圖像特征,常用CNN(如ResNet)或視覺(jué)Transformer(ViT)。 語(yǔ)言模型 :處理文本輸入/輸出,如GPT、BERT等,部分模型
    的頭像 發(fā)表于 03-17 15:32 ?7011次閱讀
    ?VLM(視覺(jué)<b class='flag-5'>語(yǔ)言</b>模型)?詳細(xì)<b class='flag-5'>解析</b>

    為什么學(xué)了C語(yǔ)言,卻寫(xiě)不出像樣的項(xiàng)目?

    在學(xué)習(xí)編程的路上,C語(yǔ)言幾乎是每個(gè)程序員的“必修課”。不管你是打算從事嵌入式開(kāi)發(fā)、系統(tǒng)編程,還是想要深入理解操作系統(tǒng)的底層原理,C語(yǔ)言都是一塊重要的基石。然而許多人在學(xué)習(xí)
    的頭像 發(fā)表于 03-14 17:37 ?612次閱讀
    為什么學(xué)了<b class='flag-5'>C</b><b class='flag-5'>語(yǔ)言</b>,卻寫(xiě)不出像樣的項(xiàng)目?

    全套C語(yǔ)言培訓(xùn)資料—PPT課件

    全套C語(yǔ)言培訓(xùn)資料,共427頁(yè),13個(gè)章節(jié):C語(yǔ)言概述、程序的靈魂—算法、數(shù)據(jù)類(lèi)型 & 運(yùn)算符與表達(dá)式、順序程序設(shè)計(jì)、選擇結(jié)構(gòu)程序設(shè)
    發(fā)表于 03-12 14:50

    分析C語(yǔ)言代碼結(jié)構(gòu)的設(shè)計(jì)問(wèn)題

    來(lái)分析一個(gè)C語(yǔ)言代碼結(jié)構(gòu)的設(shè)計(jì)問(wèn)題。 這段代碼,使用了兩次malloc,分別給 p1 和 p2 申請(qǐng)了內(nèi)存。用完后,內(nèi)存釋放,防止內(nèi)存泄漏。 大家覺(jué)得,這樣的代碼設(shè)計(jì)有沒(méi)有問(wèn)題。 代碼是某位學(xué)員在
    的頭像 發(fā)表于 02-11 09:31 ?587次閱讀

    三菱PLC編程語(yǔ)言解析

    (Sequential Function Chart, SFC)等。以下是對(duì)這些編程語(yǔ)言的簡(jiǎn)要解析: 1. 梯形圖(Ladder Diagram, LD) 梯形圖是PLC編程中最常用的圖形編程語(yǔ)言,因其
    的頭像 發(fā)表于 12-26 17:36 ?2005次閱讀

    深入理解C語(yǔ)言:循環(huán)語(yǔ)句的應(yīng)用與優(yōu)化技巧

    在程序設(shè)計(jì)中,我們常常需要重復(fù)執(zhí)行某一段代碼。為了提高效率和簡(jiǎn)化代碼,循環(huán)語(yǔ)句應(yīng)運(yùn)而生。C語(yǔ)言作為一門(mén)經(jīng)典的編程語(yǔ)言,提供了多種循環(huán)控制結(jié)構(gòu),幫助程序員高效地實(shí)現(xiàn)重復(fù)操作。掌握循環(huán)語(yǔ)句
    的頭像 發(fā)表于 12-07 01:11 ?914次閱讀
    深入理解<b class='flag-5'>C</b><b class='flag-5'>語(yǔ)言</b>:循環(huán)語(yǔ)句的應(yīng)用與優(yōu)化技巧

    KiCad的對(duì)齊工具不好用?

    “ ?不存在的。唯一的原因是您還沒(méi)有學(xué)會(huì)怎么用。 ? ” 對(duì)齊命令在哪里? KiCad的對(duì)齊命令(Align)藏得比較隱蔽,既不在菜單欄,也不在工具欄。右鍵的菜單中默認(rèn)也不存在。只有當(dāng)您 選中兩個(gè)或
    的頭像 發(fā)表于 12-04 18:15 ?1752次閱讀
    KiCad的<b class='flag-5'>對(duì)齊</b>工具不好用?

    結(jié)構(gòu)成員的順序會(huì)影響結(jié)構(gòu)的大小嗎

    相同的結(jié)構(gòu)成員,如果把順序調(diào)整一下,會(huì)不會(huì)影響結(jié)構(gòu)的大小? 答案是會(huì)的,這主要跟字節(jié)對(duì)齊有關(guān)
    的頭像 發(fā)表于 11-25 16:24 ?805次閱讀

    技術(shù)干貨驛站 ▏深入理解C語(yǔ)言:掌握C語(yǔ)言條件判斷,從if到switch的應(yīng)用

    語(yǔ)句和條件運(yùn)算符。這些結(jié)構(gòu)不僅增強(qiáng)了代碼的靈活性,還提高了程序的可讀性和可維護(hù)性。本文將深入探討C語(yǔ)言中的主要條件判斷語(yǔ)句,包括它們的語(yǔ)法、使用方法及實(shí)際應(yīng)用,通過(guò)
    的頭像 發(fā)表于 11-09 01:10 ?1180次閱讀
    技術(shù)干貨驛站 ▏深入理解<b class='flag-5'>C</b><b class='flag-5'>語(yǔ)言</b>:掌握<b class='flag-5'>C</b><b class='flag-5'>語(yǔ)言</b>條件判斷,從if到switch的應(yīng)用