#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 .
想法是如果a
是A
类型的结构那么&a.b
等于a的地址
加上b
在a
中的偏移量。由于这里使用 NULL 代替 a
的地址,因此结果只是 b
在 A
类型结构中的偏移量。
根据维基百科,
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 name
中 b
的偏移量> 如上所述并将结果转换为整数。在大多数平台上,结果应等于 sizeof(long)
。
代码中的(char*)na
将na
,即指向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/