結構體內存對齊,計算偏移量offsetof和位段

2021-10-05 04:54:30 字數 2050 閱讀 1843

結構體內存對齊是一種以空間換時間的做法,計算機可以更快的取到記憶體中某個位置的資料,防止了某些資料的二次訪問。

我們先說下結構體對齊規則:

1、成員變數要對齊到"對齊數"的整數倍上。所謂對齊數就是指編輯器預設的對齊數和該成員的大小的較小值(比如 int a;對齊數為4。

2、結構體總體大小是該結構體所有對齊數中最大的那個對齊數的整數倍。

3、當結構體巢狀結構體時,巢狀結構體的對齊數就是其最大的對齊數。

vs中預設的對齊數的值為8 linux中的預設值為4。

下來通過**展示:

struct s1 

;

sizeof(s1)=12; 我們先確定對齊數,c1的大小為1,所以根據第一條規則,對齊數為1,目前的偏移為1,i 的大小為4,根據第一條規則,對齊數為4,所以必須給c1填充3個位元組的空間,目前的偏移為4,使i進行對齊,在偏移量為4加上 i,目前的偏移為8,再在偏移量為8的位置上加上1。所以現在的偏移量9。再根據第二條規則,結構體總體大小是該結構體所有對齊數中最大的那個對齊數(4)的整數倍。所以在偏移量9之後填充3個位元組的空間。總大小為12位元組。

struct s2 ;
sizeof(s2)=8; 同理,c1,c2的對齊數為1,所以到c2時偏移量為2,i的對齊數為是4,所以填充2個空間。在加上4。總大小為8位元組。

struct s3 

;

sizeof(s3)=16 , 8+8=16;

struct s4
sizeof(s3)=32 , 8+16+8=32

我們可以通過#pragma 這個命令來修改預設對齊數

#pragma pack(2)

//設定預設對齊數為2

struct s1

;#pragma pack()

//取消設定的預設對齊數,還原為預設

這時sizeof(s1)=8

可以通過系統預設的巨集offsetof來得到每個成員的偏移量

int

main()

我們可以自己實現這個巨集;

#define  offsetof(s,m)  ((size_t)&((s*)0)->m)

//計算偏移量就是將該成員與結構體的位址第乙個成員進行相減得到,所以我們將

//第乙個成員的位址強轉為0,所以&(0->m)就是偏移的位址,隨後強轉為size_t

位段:後面的是位元位,表示該成員只佔這麼多的位元位,是為了節省空間的,不具備跨平台的特性。

1、位段的成員可以是 int unsigned int signed int 或者是 char (屬於整形家族)型別

2、位段的空間上是按照需要以4個位元組( int )或者1個位元組( char )的方式來開闢的

3、 如果相鄰位域字段的型別相同,但其位寬之和大於型別的sizeof大小,則後面的字段將從新的儲存單元開始,其偏移量為其型別大小的整數倍;(經測試此條好像僅限於char型,整型可以跨域儲存)

4、 如果相鄰的位域字段的型別不同,則各編譯器的具體實現有差異,vc6採取不壓縮方式,dev-c++採取壓縮方式;

5、 如果位域字段之間穿插著非位域字段,則不進行壓縮;

6、整個結構體的總大小為最寬基本型別成員大小的整數倍。

當我們計算偏移量時,第乙個成員認為其偏移量為0。

struct a
根據2,先來乙個int,_a,_b,_c都可以放下加起來為17,_d=30,放不下,再來乙個int,一共需要兩個int 。所以sizeof(a)=8;

不存在對齊,

struct s 

;

sizeof(s)=3;根據規則,先來乙個char,a,b都可以放下,再來乙個char,放c,再來乙個char,放d。所以一共需要3個位元組。

牛客上的一道題

struct a

;

則sizeof(struct a)的值為16,

結構體內位元組對齊偏移量

struct a int a char b int c 結構體a的大小為sizeof a 4 1 4 3 12 struct b char a int b char c 結構體b的大小為sizeof b 1 4 3 1 3 12 比如 a對齊數是1,然後b是4,b對齊後偏移量是5,不是4的整數倍,則...

計算結構體偏移量

如果能夠讓 unsigned long type 的值為0,即 type 0的時候,那麼offset的值就是簡單的 offset unsigned long type.c 如果說 type 0,那麼type.c就可以等價於 type t 0 c。但是這個語句是不能單獨存在的,因為對null指標訪問成...

動畫平移計算偏移量

private int bmpw bitmapfactory.decoderesource getresources r.drawable.cursor getwidth 獲取寬度 displaymetrics dm new displaymetrics getwindowmanager getde...