简体   繁体   English

按地址访问struct成员

[英]Accessing struct member by address

Consider a struct with two members of integer type. 考虑具有两个整数类型成员的结构。 I want to get both members by address. 我希望通过地址获得两位成员。 I can successfully get the first, but I'm getting wrong value with the second. 我可以成功获得第一个,但是我的第二个错误。 I believe that is garbage value. 我相信这是垃圾价值。 Here's my code: 这是我的代码:

#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;
}

I'm getting: 我越来越:

2 ..1 2 ..1

Can someone explain where I've gone wrong? 谁能解释我哪里出错了?

The offset of the first member must always be zero by the C standard; 根据C标准,第一个成员的偏移量必须始终为零; that's why your first cast works. 这就是你的第一次演员工作的原因。 The offset of the second member, however, may not necessarily be equal to the size of the first member of the structure because of padding. 然而,由于填充,第二构件的偏移可能不一定等于结构的第一构件的尺寸。

Moreover, adding a number to a pointer does not add the number of bytes to the address: instead, the size of the thing being pointed to is added. 此外,向指针添加数字不会向地址添加字节数:而是添加指向的事物的大小。 So when you add sizeof(int) to &f , sizeof(int)*sizeof(foo_t) gets added. 因此,当您将sizeof(int)添加到&f ,会添加sizeof(int)*sizeof(foo_t)

You can use offsetof operator if you want to do the math yourself, like this 如果你想自己做数学,你可以使用offsetof运算符,就像这样

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

The reason this works is that sizeof(char) is always one, as required by the C standard. 这样做的原因是sizeof(char) 总是一个,正如C标准所要求的那样。

Of course you can use &f.b to avoid doing the math manually. 当然你可以使用&f.b来避免手动进行数学运算。

Your problem is &f + sizeof(int) . 你的问题是&f + sizeof(int) If A is a pointer, and B is an integer, then A + B does not, in C, mean A plus B bytes. 如果A是指针,并且B是整数,那么A + B在C中不表示AB字节。 Rather, it means A plus B elements, where the size of an element is defined by the pointer type of A . 相反,它意味着AB元素,其中元素的大小由A的指针类型定义。 Therefore, if sizeof(int) is 4 on your architecture, then &f + sizeof(int) means "four foo_t s into &f , or 4 * 8 = 32 bytes into &f ". 因此,如果您的体系结构中sizeof(int)为4,则&f + sizeof(int)表示“四个foo_t s进入&f ,或者4 * 8 = 32个字节进入&f ”。

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

Or, of course, &f.a and &f.b instead, quite simply. 或者,当然, &f.a&f.b相反,非常简单。 The latter will not only give you handy int pointers anyway and relieve you of all those casts, but also be well-defined and understandable. 后者不仅会为你提供方便的int指针,而且会让你免除所有这些演员阵容,同时也能明确定义和理解。 :) :)

The expression &f + sizeof(int) adds a number to a pointer of type foo_t* . 表达式&f + sizeof(int)将数字添加到foo_t*类型的指针中。 Pointer arithmetic always assumes the pointer is to an element of an array, and the number is treated as a count of elements. 指针算术始终假定指针指向数组的元素,并将该数字视为元素计数。

So if sizeof(int) is 4, &f + sizeof(int) points four foo_t structs past f , or 4*sizeof(foo_t) bytes after &f . 因此,如果sizeof(int)为4,则&f + sizeof(int)四个foo_t结构指向f ,或者在&f之后4*sizeof(foo_t)个字节。

If you must use byte counts, something like this might work: 如果必须使用字节计数,这样的事情可能会起作用:

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

... assuming there's no padding between members a and b . ...假设成员ab之间没有填充。

But is there any reason you don't just get the value fb or the pointer &f.b ? 但是,有没有理由你不只是获得值fb或指针&f.b

You can do &f.b , and skip the actual pointer math. 你可以做&f.b ,并跳过实际的指针数学。

Here is how I would change your int b line: 以下是我将如何更改int b行:

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

BTW, when I run your program as is, I get 2 ..0 as the output. 顺便说一句,当我按原样运行你的程序时,我得到2 ..0作为输出。

This works: 这有效:

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

You are interpreting &f as a pointer and when you are adding 4 (size of int) to it, it interprets it as adding 4 pointers which is 16 or 32 bytes depending on 32 vs 64 arch. 你将&f解释为指针,当你向它添加4(int的大小)时,它会将它解释为添加4个指针,这些指针是16或32个字节,具体取决于32对64拱。 If you cast pointer to int it will properly add 4 bytes to it. 如果将指针强制转换为int,则会正确地向其添加4个字节。

This is an explanation of what is going on. 这是对正在发生的事情的解释。 I'm not sure what you are doing, but you most certainly should not be doing it like that. 我不确定你在做什么,但你肯定不应该这样做。 This can get you in trouble with alignment etc. The safe way to figure out offset of a struct element is: 这可能会让您在对齐等方面遇到麻烦。找出struct元素偏移量的安全方法是:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM