//用乙個巨集定義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...