在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

解析C語言結構體字節如何對齊

電子工程師 ? 來源:編程學習總站 ? 作者:寫代碼的牛頓 ? 2021-06-12 17:42 ? 次閱讀

01

默認字節對齊

C語言結構體字節對齊是老生常談的問題了,也是高頻面試題,現在我們來深入研究這個問題,徹底弄懂到底是怎么回事,給你一個結構體定義和平臺機器位數就能手動計算出結構體占用字節數,現在我們不使用宏#pragma pack,采用默認字節對齊方式。

先拋出結論:

在一個結構體中第一個成員變量放在偏移為0的位置,以后的變量都存儲在該變量占用字節數整數倍的地址上。

結構體總大小,必須是內部最大成員變量的整數倍,不足的補齊。

好了,現在我們直接寫個小程序驗證并分析是否真是這樣一回事。

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

這里我們定義了兩個很簡單的結構體,short占用2個字節,struct st我們一眼就知道大小了6個字節,但是struct st2呢?筆者電腦是64位,那么long占用8個字節,short占用2個字節。我們先來按照結論進行分析,在struct st2中成員變量a1在偏移0處存儲且占用8個字節,成員變量a2占用2個字節,由于8是2的倍數,所以a2在偏移8的位置存儲,又因為有結論2。

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

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; }

編譯運行輸出:

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

現在我們看一下輸出結果,struct st如我們所愿占用6個字節大小,struct st2也按照我們分析的一樣占用16個字節。我們在程序中定義了一個struct st2類型變量st_val2,從輸出中可以看出變量st_val2的a1成員變量和st_val2變量地址一樣,成員變量a2在偏移8處存儲(0x c0 = 0xb8 + 8)。一切如我們所愿,看起來好像挺簡單的,我們知道C語言有豐富的數據類型,下面我們再定義一個更復雜的結構體。

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

這個結構體包含了大量數據類型成員變量,再復雜的結構體也能按照我們的結論分析到底占用了幾個字節。

在struct st3中int型成員變量a1占用4個字節,在偏移0處存儲,char型成員變量a2占用2個字節那么應該放在2的倍數地址處存儲,a1已經占用了4個字節,所以a2應該在偏移4的地址存儲。

short型成員變量a3占用2個字節,也應該放在2的倍數地址處存儲,所以a3在偏移6的地址處存儲,a2后面填充1個字節。

long型成員變量a4占用8個字節,應該放在8的倍數地址上存儲,前面我們已經知道a3在偏移6的地址處存儲,且占用2個字節8 = 6 + 2,所以a4應該在偏移8的地址處存儲。

最后一個char型成員變量a5占用一個字節,那么a5在偏移16地址處存儲。

現在我們計算一下struct st3結構體占用空間大小,從a5偏移出計算16 + 1 = 17。在struct st3中最大成員變量占用8個字節,所以結構體總大小應該是8的倍數,最后結構體總大小是17 + 7 = 24,這里的7個字節在最后補齊。

我們依舊寫一個小程序輸出struct st3類型變量各個成員變量地址和結構體總大小。

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; }

編譯運行輸出:

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

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

枚舉類型變量和聯合體類型變量都可以作為結構體的成員變量,在分析這些結構體占用大小時,分析方法和我們上面的一模一樣,只需要把內部任何一種數據類型變量當做一個普通變量看待即可,但是結構體類型成員變量有點不一樣,它不適用于結論2,我們舉個例子。

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

在struct st4中我們定義了一個struct st3類型成員變量,前面我們已經分析過了struct st3占用24個字節。成員變量a1占用3個字節,成員變量a2占用4個字節,所以a2存儲在偏移4的地址上,在a1后面填充一個字節。成員變量a3占用8個字節,則a3存儲在偏移8的地址上。那么結構體總共占用字節數大小是:8 + 8 + 24 = 40。

最后我們寫一個程序驗證一下是否如此。

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; }

編譯運行輸出:

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宏,表示結構體按1字節對齊。也就是說結構體變量st_val3總大小是內部成員變量占用字節數總和,沒有字節填充。

現在編譯運行如下:

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字節,char型變量a2占用1個字節,short型變量a3占用2個字節,long型變量a4占用8個字節,char型變量a5占用1個字節,所以總大小是:4 + 1 + 2 + 8 + 1 = 16。如果是#pagma pack(2)呢?相信你可以自己計算了。

編輯:jq

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • C語言
    +關注

    關注

    180

    文章

    7630

    瀏覽量

    140560
  • 代碼
    +關注

    關注

    30

    文章

    4891

    瀏覽量

    70309

原文標題:C語言結構體字節對齊

文章出處:【微信號:AndroidPush,微信公眾號:Android編程精選】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦
    熱點推薦

    《ESP32S3 Arduino開發指南》第三章 C/C++語言基礎

    ++基礎,由于篇幅有限,在此僅對C/C++語言基礎進行簡單介紹。本章將分為如下9個小節:3.1 數據類型3.2 運算符3.3 表達式3.4 數組3.5 字符串3.6 注釋3.7 順序結構
    發表于 06-10 09:20

    程序設計與數據結構

    《程序設計與數據結構》重點闡述了三大方向內容: 1. C語言學習中的痛點:針對當前工程師在C語言學習中的痛點,如指針函數與函數指針,如何靈
    發表于 05-13 16:45

    深入理解C語言C語言循環控制

    C語言編程中,循環結構是至關重要的,它可以讓程序重復執行特定的代碼塊,從而提高編程效率。然而,為了避免程序進入無限循環,C語言提供了多種循
    的頭像 發表于 04-29 18:49 ?906次閱讀
    深入理解<b class='flag-5'>C</b><b class='flag-5'>語言</b>:<b class='flag-5'>C</b><b class='flag-5'>語言</b>循環控制

    C語言結構與聯合體的深度解析:內存布局與應用場景

    一、基礎概念與核心差異 1.1 結構(Struct)的本質 **結構C語言中實現數據封裝的
    發表于 04-08 09:18

    為什么學了C語言,卻寫不出像樣的項目?

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

    全套C語言培訓資料—PPT課件

    全套C語言培訓資料,共427頁,13個章節:C語言概述、程序的靈魂—算法、數據類型 & 運算符與表達式、順序程序設計、選擇結構程序設
    發表于 03-12 14:50

    分析C語言代碼結構的設計問題

    來分析一個C語言代碼結構的設計問題。 這段代碼,使用了兩次malloc,分別給 p1 和 p2 申請了內存。用完后,內存釋放,防止內存泄漏。 大家覺得,這樣的代碼設計有沒有問題。 代碼是某位學員在
    的頭像 發表于 02-11 09:31 ?326次閱讀

    三菱PLC編程語言解析

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

    KiCad的對齊工具不好用?

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

    結構成員的順序會影響結構的大小嗎

    相同的結構成員,如果把順序調整一下,會不會影響結構的大小? 答案是會的,這主要跟字節對齊有關
    的頭像 發表于 11-25 16:24 ?519次閱讀

    C語言C++中結構的區別

    同樣是結構,看看在C語言C++中有什么區別?
    的頭像 發表于 10-30 15:11 ?676次閱讀

    C語言與Java語言的對比

    C語言和Java語言都是當前編程領域中的重要成員,它們各自具有獨特的優勢和特點,適用于不同的應用場景。以下將從語法特性、內存管理、跨平臺性、性能、應用領域等多個方面對C
    的頭像 發表于 10-29 17:31 ?962次閱讀

    字節豆包推出AI智能耳機

    字節跳動旗下豆包品牌近日推出了其首款AI智能耳機——Ola Friend。這款耳機采用了開放式設計,單耳重量僅為6.6克,佩戴舒適輕盈。
    的頭像 發表于 10-10 16:55 ?969次閱讀

    技術干貨驛站 ▏深入理解C語言:編程高手必備,全方位解析運算符的核心技能!

    C語言的編程領域中,運算符是實現數據處理與邏輯操作的關鍵工具。無論是在處理簡單的數值計算,還是在構建復雜的邏輯結構時,運算符的使用貫穿始終。作為編程語言的基礎組成部分之一,運算符不僅
    的頭像 發表于 09-18 15:56 ?712次閱讀
    技術干貨驛站 ▏深入理解<b class='flag-5'>C</b><b class='flag-5'>語言</b>:編程高手必備,全方位<b class='flag-5'>解析</b>運算符的核心技能!

    技術干貨驛站 ▏深入理解C語言:掌握程序結構知識

    在計算機編程的世界中,C語言被廣泛認可為一門強大而高效的編程語言,其簡潔的語法和直接的指令使得它成為了許多程序員的首選。了解C語言的程序
    的頭像 發表于 07-27 08:45 ?1780次閱讀
    技術干貨驛站 ▏深入理解<b class='flag-5'>C</b><b class='flag-5'>語言</b>:掌握程序<b class='flag-5'>結構</b>知識
    主站蜘蛛池模板: 成人99国产精品一级毛片 | 国产福利萌白酱喷水视频铁牛 | 五月婷婷激情综合 | 中文字幕精品一区 | 啪啪免费小视频 | 老子影院午夜精品欧美视频 | 成人国产精品毛片 | 黄色毛片播放 | 欧日韩美香蕉在线观看 | 四虎影视最新网址 | 黄色视屏免费在线观看 | 四虎影院精品 | 欧美狠狠 | 7777奇米影视 | 59日本人xxxxxxxxx69 | 色偷偷成人网免费视频男人的天堂 | 又粗又硬又猛又黄的免费视频黑人 | 啪啪网站免费观看 | 高h 男男 | 国产精品人成在线播放新网站 | 国产高清在线看 | 大学生一级特黄的免费大片视频 | 一区二区三区在线播放 | 免费看吻胸亲嘴激烈网站 | 深夜在线视频免费网址 | 国产精品臀控福利在线观看 | 毛片录像| 美女一级毛片免费观看 | 黄色性生活毛片 | 亚洲深夜在线 | 日韩欧美视频在线一区二区 | 天天天综合 | 国产综合视频在线 | 国产特黄一级毛片特黄 | 四虎影院视频在线观看 | 日本x色视频| 天天操天天拍 | 黄色三级三级三级免费看 | 国产精品美女www爽爽爽视频 | 免费观看高清视频 | 日韩成人黄色 |