c語言**開發過程中,其實經常會遇到#pragma pack(n),#pragma pack(),#pragma pack(pack,n),#pragma pack(pop,n)等。並且這些語句一般出現在結構體前面。大家都知道這些是進行對齊的,但是關於是怎麼對齊的,總是理解不清晰。以下是我個人總結:
什麼是對齊?為什麼要對齊?
現代計算機中記憶體空間都是按照byte劃分的,從理論上講似乎對任何型別的變數的訪問可以從任何位址開始,但實際情況是在訪問特定變數的時候經常在特定的記憶體位址訪問,這就需要各型別資料按照一定的規則在空間上排列,而不是順序的乙個接乙個的排放,這就是對齊。
各個硬體平台對儲存空間的處理上有很大的不同。一些平台對某些特定型別的資料只能從某些特定位址開始訪問。其他平台可能沒有這種情況,但是最常見的是如果不按照適合其平台要求對資料存放進行對齊,會在訪問效率上帶來損失。比如有些平台每次讀都是從偶位址開始,如果乙個int型(假設為32位系統)如果存放在偶位址開始的地方,那麼乙個讀週期就可以讀出,而如果存放在奇位址開始的地方,就可能會需要2個讀週期,並對兩次讀出的結果的高低位元組進行拼湊才能得到該int資料。顯然在讀取效率上下降很多。這也是空間和時間的博弈。
在c語言編譯器中提供了#pragma pack(n)來設定變數以n位元組對齊方式。n位元組對齊就是說變數存放的起始位址的偏移量有兩種情況:
第一:如果n大於等於該變數所占用的位元組數,那麼偏移量必須滿足預設的對齊方式;
第二:如果n小於該變數的型別所占用的位元組數,那麼偏移量為n的倍數,不用滿足預設的對齊方式。結構的總大小也有個約束條件,分下面兩種情況:如果n大於所有成員變數型別所占用的位元組數,那麼結構的總大小必須為占用空間最大的變數占用的空間數的倍數;否則必須為n的倍數。
#include #include #include typedef char int8;
typedef unsigned char uint8;
typedef short int16;
typedef unsigned short uint16;
typedef int int32;
typedef unsigned int uint32;
typedef long long int64;
typedef unsigned long long uint64;
#pragma pack(1)
typedef struct pack_modular_message_t;
#pragma pack(0)
typedef struct no_pack_modular_message_t;
int main()
編譯執行結果:
zhang@ubuntu140453200:/mnt/external/zhang/test/mzh$ ./struct_pragma_pack
pack struct size 62
no pack struct size 64
zhang@ubuntu140453200:/mnt/external/zhang/test/mzh$
pragma pack n 與記憶體對其問題
title pragma pack n 與記憶體對其問題 date 2016 06 08 15 32 11 categories c tags c c 記憶體對齊 pragma pack 作用 遮蔽掉編譯器為變數設定的預設的對其方式,設定自己的對其方式 而 pragma pack n 表示設定變數以...
rust對結構體排序
use std cmp ordering use rand rng 匯入外部的包.記得修改toml檔案 保證age是可比較的 pub struct person t std cmp partialord 注意泛型t的位置 impl t person t where t std cmp partial...
對結構體初始化
對結構體 struct a 有幾種初始化方式 struct a a1 或者struct a a1 或者struct a a1 核心喜歡用第一種,使用第一種和第二種時,成員初始化順序可變。轉一篇文章 在閱讀gnu linux核心 時,我們會遇到一種特殊的結構初始化方式。該方式是某些c教材 如譚二版 k...