这样可以避免UB吗 [英] Does this avoid UB
问题描述
这个问题更像是一个学术性的问题,因为现在没有足够的理由编写自己的offsetof
宏.不过,我在这里和那里都看到了这个本地实现的弹出窗口:
This question is more of an academic one, seeing as there is no valid reason to write your own offsetof
macro anymore. Nevertheless, I've seen this home-grown implementation pop-up here and there:
#define offsetof(s, m) ((size_t) &(((s *)0)->m))
从技术上讲,这是在取消引用NULL指针(AFAIKT):
Which is, technically speaking, dereferencing a NULL pointer (AFAIKT):
C11(ISO/IEC 9899:201x)§6.3.2.3指针第3节
具有值0
的整数常量表达式,或强制转换为类型void *
的此类表达式,称为空指针常量
An integer constant expression with the value 0
, or such an expression cast to type void *
, is called a null pointer constant
因此,根据我对标准的理解方式,以上实现与编写相同:
So the above implementation is, according to how I read the standard, the same as writing:
#define offsetof(s, m) ((size_t) &(((s *)NULL)->m))
这确实使我感到奇怪,通过更改一个微小的细节,offsetof
的以下定义将完全合法,和可靠:
It does make me wonder that, by changing one tiny detail, the following definition of offsetof
would be completely legal, and reliable:
#define offsetof(s, m) (((size_t)&(((s *) 1)->m)) - 1)
看到的不是1而是0,而是1,最后我减去1,结果应该是相同的.我不再使用NULL指针.据我所知结果是相同的.
Seeing as, instead of 0, 1 is used as a pointer, and I subtract 1 at the end, the result should be the same. I'm no longer using a NULL pointer. As far as I can tell the results are the same.
所以基本上:有什么理由为什么在此offsetof
定义中使用1
代替0
可能不起作用?在某些情况下,它仍然会导致UB吗?如果是的话:何时以及如何?基本上,我要问的是:我在这里错过了什么吗?
So basically: is there any reason why using 1
instead of 0
in this offsetof
definition might not work? Can it still cause UB in certain cases, and if so: when and how? Basically, what I'm asking here is: Am I missing anything here?
推荐答案
两个定义都是未定义的行为:在第一个定义中,空指针已被取消引用,而在第二个定义中,您正在引用无效的指针(该指针未指向有效对象).在C语言中,无法编写offsetof
宏的可移植版本.
Both definitions are undefined behavior: in the first definition a null pointer is dereferenced and in your second definition you are dereferencing an invalid pointer (the pointer does not point to a valid object). It is not possible in C to write a portable version of offsetof
macro.
缺陷报告#44 说:
尤其是这就是为什么存在offsetof宏的原因:否则,没有可移植的方法来计算此类转换时间常数."
"In particular, this is why the offsetof macro exists: there was otherwise no portable means to compute such translation-time constants."
(DR#44用于C89,但C99和C11的语言没有任何变化,可以实现可移植的实现.)
(DR#44 is for C89 but nothing has changed in the language in C99 and C11 that would allow a portable implementation.)
这篇关于这样可以避免UB吗的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!