按地址访问struct成员

时间:2012-12-31 03:05:28

标签: c pointers struct

考虑一个包含两个整数类型成员的结构。我希望通过地址获得两位成员。我可以成功获得第一个,但是我的第二个错误。我相信这是垃圾价值。这是我的代码:

#include <stdio.h>

typedef struct { int a; int b; } foo_t;

int main(int argc, char **argv)
{

  foo_t f;
  f.a = 2;
  f.b = 4;
  int a = ((int)(*(int*) &f));
  int b = ((int)(*(((int*)(&f + sizeof(int)))))); 
  printf("%d ..%d\n", a, b);
  return 0;
}

我得到了:

  

2 ..1

有人可以解释我出错的地方吗?

5 个答案:

答案 0 :(得分:7)

第一个成员的偏移量必须始终为C标准的零;这就是你的第一次演员工作的原因。但是,由于填充,第二个成员的偏移量可能不一定等于结构的第一个成员的大小。

此外,向指针添加数字不会向地址添加字节数:而是添加指向的事物的大小。因此,当您向sizeof(int)添加&f时,会添加sizeof(int)*sizeof(foo_t)

如果您想自己进行数学运算,可以使用offsetof运算符,例如

int b = *((int*)(((char*)&f)+offsetof(foo_t, b)));

这有效的原因是sizeof(char) 总是一个,符合C标准的要求。

当然,您可以使用&f.b来避免手动进行数学运算。

答案 1 :(得分:2)

您的问题是&f + sizeof(int)。如果A是指针,并且B是整数,那么{C}中的A + B不会表示AB个字节。相反,它意味着AB个元素,其中元素的大小由A的指针类型定义。因此,如果您的体系结构中sizeof(int)为4,则&f + sizeof(int)表示“foo_t四个&f,或&f中的4 * 8 = 32个字节”

请尝试((char *)&f) + sizeof(int)

或者,当然,&f.a&f.b相反,非常简单。后者不仅会给你提供方便的int指针,而且会让你免除所有这些演员阵容,同时也能明确定义和理解。 :)

答案 2 :(得分:2)

表达式&f + sizeof(int)为类型为foo_t*的指针添加数字。指针算术始终假定指针指向数组的元素,并将该数字视为元素计数。

因此,如果sizeof(int)为4,则&f + sizeof(int)指向foo_t之后的四个f结构,或4*sizeof(foo_t)之后的&f字节。

如果必须使用字节计数,这样的事情可能会起作用:

int b = *(int*)((char*)(&f) + sizeof(int));

...假设成员ab之间没有填充。

但是,您是否有任何理由不仅获得值f.b或指针&f.b

答案 3 :(得分:1)

您可以执行&f.b,并跳过实际的指针数学。

以下是我如何更改int b行:

int b = (int)(*(((int*)(&(f.b)))));

顺便说一句,当我按原样运行你的程序时,我得到2 ..0作为输出。

答案 4 :(得分:1)

这有效:

  int b = ((int)(*(int*)((int)&f + sizeof(int))));

您正在将&amp; f解释为指针,当您向其添加4(int的大小)时,它会将其解释为添加4个指针,这些指针是16或32个字节,具体取决于32对64拱。如果将指针强制转换为int,则会正确地向其添加4个字节。

这是对正在发生的事情的解释。我不确定你在做什么,但你肯定不应该这样做。这可能会使您在对齐等方面遇到麻烦。找出struct元素偏移量的安全方法是:

  printf("%d\n", &(((foo_t *)NULL)->b));