为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

白衣非少年 2019-12-15 16:12:45
在ANSI C中,offsetof定义如下。#define offsetof(st, m) \    ((size_t) ( (char *)&((st *)(0))->m - (char *)0 ))为什么由于我们取消引用NULL指针,这为什么不会引发分段错误?还是这种编译器黑客看到了偏移量的唯一地址,因此它静态地计算了地址而没有实际取消引用呢?此代码也可移植吗?
查看完整描述

3 回答

?
慕尼黑8549860

TA贡献1818条经验 获得超11个赞

上面的代码中没有任何内容被取消引用。当在地址值上使用*或->查找引用的值时,将发生取消引用。*上面的唯一用途是用于类型转换的类型声明。


在->操作上面使用,但它不是用来访问值。相反,它用于获取值的地址。这是一个非宏代码示例,应使其更清晰一些


SomeType *pSomeType = GetTheValue();

int* pMember = &(pSomeType->SomeIntMember);

第二行实际上并不会导致取消引用(取决于实现)。它只是返回值SomeIntMember内的地址pSomeType。


您看到的是在任意类型和char指针之间进行了大量转换。使用char的原因是,它是C89标准中唯一具有明确大小的类型之一(也许是唯一)。大小为1。通过确保大小为1,上述代码可以达到计算值的真实偏移量的魔力。



查看完整回答
反对 回复 2019-12-16
?
素胚勾勒不出你

TA贡献1827条经验 获得超9个赞

尽管这是的典型实现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))

那是某种编译器错误,尤其是因为标头是随编译器一起分发的,因此不起作用



查看完整回答
反对 回复 2019-12-16
  • 3 回答
  • 0 关注
  • 572 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信