这样可以避免UB吗 [英] Does this avoid UB

查看:112
本文介绍了这样可以避免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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆