[英]Getting the offset of a member variable via casting a nullptr
我正在查看<cstddef>
的宏offsetof
,發現可能的實現是通過
#define my_offsetof(type, member) ((void*) &(((type*)nullptr)->member))
我嘗試過,確實可以按預期工作
#include <iostream>
#define my_offsetof(type, member) ((void*) &(((type*)nullptr)->member))
struct S
{
char x;
short y;
int z;
};
int main()
{
std::cout << my_offsetof(S, x) << '\n';
std::cout << my_offsetof(S, y) << '\n';
std::cout << my_offsetof(S, z) << '\n';
S s;
std::cout << (void*) &((&s)->x) << '\n'; // no more relative offsets
std::cout << (void*) &((&s)->y) << '\n'; // no more relative offsets
std::cout << (void*) &((&s)->z) << '\n'; // no more relative offsets
}
我所做的唯一修改是,我使用最終強制轉換為void*
而不是size_t
,因為我想將地址顯示為指針。
我的問題:
nullptr
“訪問”成員然后獲取其地址是否合法? 如果是這樣,那么似乎&(((type*)nullptr)->member)
計算成員相對於0的地址,確實是這種情況嗎? (看起來是這樣,在最后3行中,我獲得了相對於s
地址的偏移量)。 (void*)
的最終轉換,則會出現段錯誤。 為什么? &(((type*)nullptr)->member)
應該是type*
類型的指針,還是在這里以某種方式刪除了類型?
- 該代碼完全合法嗎?
不, 這是未定義的行為 。 編譯器可以選擇以這種方式實現offsetof
,但這是因為它是實現:它可以選擇如何實現自己的功能。 另一方面,您不會得到這種“奢華”。
您無法實現offsetof
宏。 並非以任何符合標准的方式。
- 如果我從宏定義中刪除對(void *)的最終轉換,則會出現段錯誤。 為什么? &(((((type *)nullptr)-> member)不應該是type *類型的指針,還是在這里以某種方式刪除了類型?
嘗試打印my_offsetof(S, x)
可能是一個段my_offsetof(S, x)
因為x
是char
並且該表達式導致char*
),因為std::ostream
的operator<<
將嘗試將char*
打印為C樣式字符串 。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.