c - 如何计算结构的偏移量?在这里解释一下 printf 语句?

标签 c pointers casting printf offset

#include<stdio.h>
main()
{
        unsigned char c;
        typedef struct name {
                long  a;
                int b;
                long c;
        }r;
        r re = {3,4,5};
        r *na = &re;
        printf("%d", *(int*) ((char*)na + (unsigned int) & ( (struct name *)0 )->b));
}

输出:

4

如果有人能详细解释一下 printf 语句在这个 C 程序中的作用,我将不胜感激?根据我的说法, int 是 casted 。然后 char 指针被转换为 na。但我不明白整个陈述总体上在做什么?在这里做什么类型转换? b 不是指针,但它似乎用作指针。我在 c 编程书籍之一中发现了这个问题。它似乎是在计算结构偏移量,但我仍然不知道如何计算。请帮助我详细了解程序。

最佳答案

代码 &((struct name *)0)->b 确实被称为“offsetof”操作,实际上是一个 well-known C macro .

想法是如果aA类型的结构那么&a.b等于a的地址加上ba中的偏移量。由于这里使用 NULL 代替 a 的地址,因此结果只是 bA 类型结构中的偏移量。

根据维基百科,

This works by casting a null pointer into a pointer to structure st, and then obtaining the address of member m within said structure. While this implementation works correctly in many compilers, it has undefined behavior according to the C standard,2 since it involves a dereference of a null pointer (although, one might argue that no dereferencing takes place, because the whole expression is calculated at compile time)

那么让我们一步一步地看一下printf中的表达式。

表达式 (unsigned int) & ( (struct name *)0 )->b)) 计算 struct nameb 的偏移量> 如上所述并将结果转换为整数。在大多数平台上,结果应等于 sizeof(long)

代码中的(char*)nana,即指向struct name的指针转换为char指针。这是必需的,因为 sizeof(char) 可以假定为 1 而 sizeof(*na) 大于 1。我们要做的是使用地址*na 作为原始数字地址而不是 pointer arithmetic ,因此如果例如 na==0x1234,则 ((char*)na + 4) 的结果等于 0x1234 + 4 = 0x1238.

总和产生一个内存地址。该地址等于对象na中成员变量b的地址,类型为char *。知道了,最后一步是将地址转换回int *(因为b的类型是int)然后取消引用结果(再一次,我们知道它指向 b)。最终结果是 b 的值,然后打印出来。

关于c - 如何计算结构的偏移量?在这里解释一下 printf 语句?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34619261/

相关文章:

c - C 编译器是否修复了一些明显的内存泄漏?

c - 插入链表无法正常工作

C++从 vector 中删除指针导致堆错误

c - 为什么++不能正确递增?

c# - 如何使用反射将未知属性正确地转换为从公共(public)基础派生的通用列表?

c - 使用 sscanf() 截断字符串

c - 如何从特定数字中获取值?

c++ - 实例化对象的堆栈和堆分配 C++

sql - 在 SQL Server 中使用 CAST() 和子查询过滤记录

c# - 在 Unity 中使用 GetComponent 时通过基类管理派生类?