在C中进行类型转换的宏,详细了解偏移量

时间:2013-11-10 02:22:42

标签: c offsetof

以下代码及其输出:

#include <stdio.h>
int x = 0;
     #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)x)->MEMBER)
     #define offsetof_1(TYPE, MEMBER) ((size_t) &((TYPE *)1)->MEMBER)
     #define offsetof_2(TYPE, MEMBER) ((size_t) &((TYPE *)2)->MEMBER)
     #define offsetof_3(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
struct test{};
struct m {
     int b;
     char w;
     struct test t;
     int c;
    };
int main(void) {

    printf("Checking:%x\n",offsetof(struct m,b));
    printf("Checking:%x\n",offsetof_1(struct m,b));
    printf("Checking:%x\n",offsetof_2(struct m,b));
    printf("Checking:%x\n",offsetof_3(struct m,b));
    return 0;
}
Output:
Checking:0
Checking:1
Checking:2
Checking:0

我想了解这里使用的类型转换。我认为,编译器如何处理它将(type *)(value)视为从address(value)开始的类型。因此,对于给定的结构,期望值为0,即。 offsetof是b,但是由于我们使用不同的类型进行类型转换,我们得到不同的偏移量。如果我的理解是正确的,请告诉我。我只是想了解文字的类型化及其含义。这用于Linux内核。因此也标记它们。

1 个答案:

答案 0 :(得分:2)

offsetof是标准设施。 C标准将其定义为以某种方式运行,但没有定义编译器如何实现它。大多数编译器依赖于未定义的行为,为了offsetof实现而定义了一个特例。

你所做的就是语言语义而言是无稽之谈。将值2视为指针是未定义行为的典型示例。

用户无法定义自己的offsetof语言的设计意图,因此最好不要尝试。

“引擎盖下”,是指针通常是机器寄存器中保存的标量,标量算法用于获取结构成员的地址。执行相同的算术以在“位置零”处获取对象的地址,在任何对象内产生其通用偏移。使用除零之外的整数作为位置可能产生算术结果,或者它可能不会。 (它通常会,但这个想法是无稽之谈。)

尝试使用概念性无意义的程序是发现系统工作方式的一种危险方法,因为它会冒着标记错误或采取检测到错误的快捷方式的风险。