为什么 offsetof() 的这种实现有效? [英] Why does this implementation of offsetof() work?

查看:19
本文介绍了为什么 offsetof() 的这种实现有效?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在 ANSI C 中,offsetof 定义如下.

In ANSI C, offsetof is defined as below.

#define offsetof(st, m) 
    ((size_t) ( (char *)&((st *)(0))->m - (char *)0 ))

为什么这不会引发分段错误,因为我们正在取消引用 NULL 指针?或者这是某种编译器黑客,它看到只有偏移量的地址被取出,所以它静态计算地址而不实际取消引用它?还有这个代码可移植吗?

Why won't this throw a segmentation fault since we are dereferencing a NULL pointer? Or is this some sort of compiler hack where it sees that only address of the offset is taken out, so it statically calculates the address without actually dereferencing it? Also is this code portable?

推荐答案

上述代码中没有任何地方取消引用.当在地址值上使用 *-> 以查找引用值时,会发生取消引用.上面 * 的唯一用途是在类型声明中用于强制转换.

At no point in the above code is anything dereferenced. A dereference occurs when the * or -> is used on an address value to find referenced value. The only use of * above is in a type declaration for the purpose of casting.

-> 运算符在上面使用,但不用于访问值.相反,它用于获取值的地址.这是一个非宏代码示例,应该使它更清晰

The -> operator is used above but it's not used to access the value. Instead it's used to grab the address of the value. Here is a non-macro code sample that should make it a bit clearer

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

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

The second line does not actually cause a dereference (implementation dependent). It simply returns the address of SomeIntMember within the pSomeType value.

你看到的是任意类型和字符指针之间的大量转换.char 的原因是它是 C89 标准中唯一(可能是唯一)具有明确大小的类型之一.大小为 1.通过确保大小为 1,上面的代码可以实现计算值的真实偏移量的邪恶魔法.

What you see is a lot of casting between arbitrary types and char pointers. The reason for char is that it's one of the only type (perhaps the only) type in the C89 standard which has an explicit size. The size is 1. By ensuring the size is one, the above code can do the evil magic of calculating the true offset of the value.

这篇关于为什么 offsetof() 的这种实现有效?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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