strutd對齊問題

2021-07-25 08:56:39 字數 4009 閱讀 8517

//用乙個巨集定義find求結構體struct s中某個成員變數member相對struct s的偏移量.

//思考:若struct s的位址為0,則其成員member的位址就是其相對於s的偏移量

//擴充套件: <1>sizeof(struct s) 不一定等於 sizeof(struct s中的每乙個成員)的和

//      <2>結構體大小不僅由成員的大小決定(sizeof(member)),而且還要考慮編譯器用來優化的對齊。

// 編譯器的優化對齊(alignment), 是為了減少訪問匯流排的次數。

//由於資料匯流排的位數(由機器字長決定),為了減少資料訪問的次數。

//這樣可以保證機器字長整數倍的基本型別(而非自定義型別)

//能夠通過 sizeof(基本型別)/sizeof(size_t)次匯流排訪問完成;

//通過實驗, 我得出的對齊規則是:

// char  偏移位址二進位制的最後一位:0/1;即1的倍數的位址對齊性;即任意對齊性;

// short 偏移位址二進位制的最後一位:0;  即2的倍數字址的對齊性;即偶數字址對齊性;

// int     偏移位址二進位制的最後兩位:00; 即4的倍數的位址對齊性;

// long long   偏移位址二進位制的最後三位:000;即8的倍數的位址對齊性;

// double偏移位址二進位制的最後三位:000;即8的倍數的位址對齊性;

//總之,struct中基本型別成員的偏移位址時一定是sizeof(基本型別)的整數倍,

//自定義型別偏移位址的對齊性是任意的.

//推過這種方式,就能解釋sizeof(struct s)不等於所有成員的sizeof的和。

// sizeof(struct s) 除了滿足以上偏移位址對齊外,

// 是其大小為其基本型別成員的sizeof值最大的成員的sizeof值的整數倍

// 也就是說為最大的基本型別的sizeof值得整數倍。

程式舉例:

[cpp]view plain

copy

#include 

using

namespace

std;  

struct

cc ;  

struct

student ;  

//用乙個巨集定義find求結構體struct s中某個成員變數member相對struct s的偏移量.

//思考:若struct s的位址為0,則其成員member的位址就是其相對於s的偏移量

//擴充套件: <1>sizeof(struct s) 不一定等於 sizeof(struct s中的每乙個成員)的和

//      <2>結構體大小不僅由成員的大小決定(sizeof(member)),而且還要考慮編譯器用來優化的對齊。

// 編譯器的優化對齊(alignment), 是為了減少訪問匯流排的次數。

//由於資料匯流排的位數(由機器字長決定),為了減少資料訪問的次數。

//這樣可以保證機器字長整數倍的基本型別(而非自定義型別)

//能夠通過 sizeof(基本型別)/sizeof(size_t)此匯流排訪問完成;

//通過實驗, 我得出的對齊規則是:

// char  偏移位址二進位制的最後一位:0/1;即1的倍數的位址對齊性;即任意對齊性;

// short 偏移位址二進位制的最後一位:0;  即2的倍數字址的對齊性;即偶數字址對齊性;

// int   偏移位址二進位制的最後兩位:00; 即4的倍數的位址對齊性;

// float 偏移位址二進位制的最後兩位:00; 即4的倍數的位址對齊性;

// long  偏移位址二進位制的最後三位:000;即8的倍數的位址對齊性;

// double偏移位址二進位制的最後三位:000;即8的倍數的位址對齊性;

//總之,struct中基本型別成員的偏移位址時一定是sizeof(基本型別)的整數倍,

//自定義型別偏移位址的對齊性是任意的.

//推過這種方式,就能解釋sizeof(struct s)不等於所有成員的sizeof的和。

// sizeof(struct s) 除了滿足以上偏移位址對齊外,

// 是其大小為其基本型別成員的sizeof值最大的成員的sizeof值的整數倍

// 也就是說為最大的基本型別的sizeof值得整數倍。

#define find(s, member)  (size_t)(&((*((s *)((void *)0))).member))

#define find1(s, member) (size_t)(&(*((s *)0)).member)

#define find2(s, member) (size_t)(&(((s *)0)->member))

#define displacement1(structure, member) (size_t) &((*((structure *)0)).member)

#define displacement2(structure, member) (size_t) &(((structure *)0)->member)

struct

c ;  

struct

ccc ;  

struct

d ;  

struct

e ;           //24

struct

f ;  

struct

g ;  

// 12

intmain()    

補充:首先要明確sizeof不是函式,也不是一元運算子,//這個有待商榷,因為運算子優先順序裡有它。

他是個類似巨集定義的特殊關鍵字,sizeof();

括號內在編譯過程中是不被編譯的,而是被替代型別,

如 int a=8;sizeof(a);

在編譯過程中,它不管a的值是什麼,只是被替換成型別 sizeof(int); 結果為4.

如果sizeof(a=6);呢,也是一樣的轉換成a的型別,但是要注意 因為a=6是不被編譯的,所以執行完sizeof(a=6);a的值還是8,是不變的!

記住以下幾個結論:

1.unsigned影響的只是最高位bit的意義(正負),資料長度不會被改變的。所以sizeof(unsigned int) == sizeof(int);

2.自定義型別的sizeof取值等同於它的型別原形。如typedef short word;sizeof(short) == sizeof(word)。

3.對函式使用sizeof,在編譯階段會被函式返回值的型別取代。如:int f1();

cout <

char a = 「abcdef 「;

int b[20] = ;

char c[2][3] = ;

cout << sizeof(a) << endl; // 7

cout << sizeof(b) << endl; // 20*4

cout << sizeof(c) << endl; // 6

陣列a的大小在定義時未指定,編譯時給它分配的空間是按照初始化的值確定的,也就是7,包括『\0』的。

6.字串的sizeof和strlen,用例子說明:

char a = 「abcdef 「;

char b[20] = 「abcdef 「;

string s = 「abcdef 「;

cout << strlen(a) << endl; // 6,字串長度

cout << sizeof(a) << endl; // 7,字串容量

cout << strlen(b) << endl; // 6,字串長度

cout << sizeof(b) << endl; // 20,字串容量

cout << sizeof(s) << endl; //4, 這裡不代表字串的長度,而是string類的大小

cout << strlen(s) << endl; // 錯誤!s不是乙個字元指標。

cout << strlen(s.c_str()) << endl;

a[1] = '\0';

cout <

位元組對齊問題

現代計算機中記憶體空間都是按照byte劃分的,從理論上講似乎對任何型別的變數的訪問可以從任何位址開始,但實際情況是在訪問特定型別變數的時候經常在特 定的記憶體位址訪問,這就需要各種型別資料按照一定的規則在空間上排列,而不是順序的乙個接乙個的排放,這就是對齊。對齊的作用和原因 各個硬體平台對儲存空間的...

位元組對齊問題

1 什麼是位元組對齊問題?一般來說,計算機按照其字長方式來定址可以提高執行效率,比如32位 4位元組 的x86 結構下,如果每次訪問的變數其位址都是4的倍數,則每次對變數的訪問只需要一次匯流排 操作。因此,編譯器為了迎合cpu的這一特性,一般在編譯的時候都會對變數的儲存方式 進行對齊處理。當然x86...

位元組對齊問題

位元組序問題關係到資料結構設計的是否合理,合理的資料結構設計可以節省記憶體空間,同時還能夠提高資料訪問效率,這在資源有限的其嵌入式系統中是非常重要的.我們可以先看看這兩個例子就大概了解了位元組對齊的問題了。在pc機上char是佔1個位元組,而int是4個位元組。include include voi...