Does this implementation of offsetof invoke undefined behavior? [duplicate]

佐手、 提交于 2021-02-04 06:28:05

问题


offsetof is defined like this in stddef.h:

#define offsetof(type, member) ((size_t)&((type *)0)->member)

Does this invoke undefined behavior due to the dereference of a NULL pointer? If not, why?


回答1:


In normal C code, the behavior of ((size_t)&((type *)0)->member) is not specified by the C standard:

  • First, per C 2018 6.5.2.3 4, about ->, ((type *)0)->member designates the lvalue of the member member of the structure to which (type *)0 points. But ((type *)0) does not point to a structure, and therefore there is no member this can be the lvalue of.
  • Supposing it does give an lvalue for some hypothetical structure, there is no guarantee that taking its address and converting it to size_t yields the offset of the member, both because we do not know that (type *)0 yields an address that is actually represented with zero in the implementation’s addressing scheme and because the conversion of a pointer to an integer specified by C 2018 6.3.2.3 6 only tells us the result is implementation-defined, not that it yields the address in any otherwise meaningful form.

Were this code in a standard header, such as <stddef.h>, it is under the control of the C implementation and not the C standard, and so questions about whether it is undefined according to the C standard do not apply. The C standard only says how the standard headers behave when included—an implementation may use any means it chooses to achieve the required effects, whether that is simply defining the behavior of source code that is not fully defined by the C standard or putting source code in an entirely different language in the headers. (In fact, the file stddef.h could be entirely empty or not exist at all, and the compiler could supply its required declarations when it sees #include <stddef.h> without reading any actual file from disk.)




回答2:


Leaving aside all the other reasons why it might not be a correct implementation of offsetof,

#define offsetof(type, member) ((size_t)&((type *)0)->member)

is not appropriate even as part of the implementation because everything in stddef.h must work correctly in both C and C++, and in C++, the above construct definitely will misbehave in the presence of overloaded operator->. This is why GCC's stddef.h switched to using a special intrinsic function called __builtin_offsetof upwards of fifteen years ago.

Yes, I am saying that if you saw this in some stddef.h, that stddef.h is buggy.



来源:https://stackoverflow.com/questions/57342141/does-this-implementation-of-offsetof-invoke-undefined-behavior

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!