1、c語言的結構體中,因為字節對齊的問題,導致成員地址並不能根據類型的大小進行計算。例如:
struct test { char ch; int a; } printf("test的大小=%d",sizeof(struct test)); //答案是8
/*注意下面第二個char *,必須是char型指針(和結構體第一個成員類型一致),
**因為你強制轉換的是一個地址,所以必須用指針類型。
**另外一個地址只有有了類型才可以進行加減運算,否在地址+1不知道要移動幾個字節。
*/ int *p=(int *)(char *)&test+1; //錯誤,因為char並不是占用1個字節,而是4個字節 int *p=(int *)(char *)%test+4; //正確
2、offsetof宏的實現如下:
#define offsetof(TYPE,MEMBER) (size_t) &((TYPE *)0)->MEMBER)
哈哈,復雜吧,解釋一下:由於造成空洞的對齊動作是由編譯器負責完成的,這里有一個欺騙編譯器的指令:((TYPE *)0),
意思是定義一個指向TYPE類型的指針,且該指針值(也就是該type類型的地址)為0,當然這是不可能引用成功的,0地址早已
被操作系統保護起來了:),那么這么做意義何在?我們知道:當前地址-首地址=偏移量,如果首地址為0呢?當前地址是不是
就是偏移量了?呵呵,明白了吧,強制把0轉換為type類型的指針,並不是為了訪問0地址的值,而是為了從編譯器里套話(假設首地址
為0時,當前地址是多少?)。
最后要注意:因為我們得到的是一個地址,所以要設置為size_t類型,如果設為int類型,編譯器就要警告了,因為int和size_t的大小不相同。
最后以編譯器的警告信息作為本文章的結尾吧:
warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]