为什么此offsetof()实现有效?

在ANSI C中,offsetof定义如下。


#define offsetof(st, m) \

    ((size_t) ( (char *)&((st *)(0))->m - (char *)0 ))

为什么由于我们取消引用NULL指针,这为什么不会引发分段错误?还是这种编译器黑客看到了偏移量的唯一地址,因此它静态地计算了地址而没有实际取消引用呢?此代码也可移植吗?


白衣非少年
浏览 583回答 3
3回答

慕尼黑8549860

上面的代码中没有任何内容被取消引用。当在地址值上使用*或->查找引用的值时,将发生取消引用。*上面的唯一用途是用于类型转换的类型声明。在->操作上面使用,但它不是用来访问值。相反,它用于获取值的地址。这是一个非宏代码示例,应使其更清晰一些SomeType *pSomeType = GetTheValue();int* pMember = &(pSomeType->SomeIntMember);第二行实际上并不会导致取消引用(取决于实现)。它只是返回值SomeIntMember内的地址pSomeType。您看到的是在任意类型和char指针之间进行了大量转换。使用char的原因是,它是C89标准中唯一具有明确大小的类型之一(也许是唯一)。大小为1。通过确保大小为1,上述代码可以达到计算值的真实偏移量的魔力。

素胚勾勒不出你

尽管这是的典型实现offsetof,但该标准并没有强制要求该标准:在标准标头中定义了以下类型和宏<stddef.h>[...]offsetof(type,member-designator)它扩展为一个整数常量表达式,其类型为size_t,member-designator从其结构的开头(由表示)到结构成员(由表示)的偏移量(以字节为单位type)。类型和成员代号应使statictypet;然后该表达式求值为一个地址常数。(如果指定的成员是位字段,则行为未定义。)&(t.member-designator)阅读PJ Plauger的“标准C库”以获取有关该库以及其他<stddef.h>所有项目的讨论,这些项目可能都是(应该?)使用适当的语言编写的边界功能,并且可能需要特殊的编译器支持。它仅具有历史意义,但是我在386 / IX上使用了较早的ANSI C编译器(请参阅,大约在1990年,我告诉过您历史性的意义),该版本在该版本上崩溃了,offsetof但当我将其修改为:#define offsetof(st, m) ((size_t)((char *)&((st *)(1024))->m - (char *)1024))那是某种编译器错误,尤其是因为标头是随编译器一起分发的,因此不起作用
打开App,查看更多内容
随时随地看视频慕课网APP