//用乙個巨集定義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 偏移位址二進位制的最後兩位: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 <
參考 :
struct的成員對齊
struct 的成員對齊 intel 微軟等公司曾經出過一道類似的面試題 include pragma pack 8 struct example1 struct example2 pragma pack int main int argc,char argv 問程式的輸入結果是什麼?答案是 8 1...
struct的成員對齊
1struct 的成員對齊 intel 微軟等公司曾經出過一道類似的面試題 include pragma pack 8 struct example1 struct example2 pragma pack int main int argc,char argv 問程式的輸入結果是什麼?答案是 8 ...
struct的成員對齊
intel 微軟等公司曾經出過一道類似的面試題 1.include 2.pragma pack 8 3.struct example1 4.8.struct example2 9.14.pragma pack 15.int main int argc,char argv 16.問程式的輸入結果是什麼...