C语言 在 c 中查找结构元素的偏移量
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/18749349/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Finding offset of a structure element in c
提问by MSB
struct a
{
struct b
{
int i;
float j;
}x;
struct c
{
int k;
float l;
}y;
}z;
Can anybody explain me how to find the offset of int kso that we can find the address of int i?
谁能解释一下如何找到 的偏移量int k以便我们可以找到 的地址int i?
回答by Gangadhar
Use offsetof()to find the offset from the start of zor from the start of x.
使用offsetof()发现,从开始的偏移z或开始x。
offsetof()- offset of a structure member
offsetof()- 结构成员的偏移
SYNOPSIS
概要
#include <stddef.h>
size_t offsetof(type, member);
offsetof()returns the offset of the field member from the
start of the structure type.
offsetof()返回字段成员从结构类型开始处的偏移量。
EXAMPLE
例子
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
int
main(void)
{
struct s {
int i;
char c;
double d;
char a[];
};
/* Output is compiler dependent */
printf("offsets: i=%ld; c=%ld; d=%ld a=%ld\n",
(long) offsetof(struct s, i),
(long) offsetof(struct s, c),
(long) offsetof(struct s, d),
(long) offsetof(struct s, a));
printf("sizeof(struct s)=%ld\n", (long) sizeof(struct s));
exit(EXIT_SUCCESS);
}
You will get the following output on a Linux, if you compile with GCC:
如果您使用 GCC 编译,您将在 Linux 上获得以下输出:
offsets: i=0; c=4; d=8 a=16
sizeof(struct s)=16
回答by silen
It's been 3 years since the question has been asked, I'm adding my answer for the sake of completeness.
自从提出这个问题已经 3 年了,为了完整起见,我正在添加我的答案。
The hacky way of getting the offset of a struct member goes like this
获取 struct 成员偏移量的 hacky 方法是这样的
printf("%p\n", (void*)(&((struct s *)NULL)->i));
It doesn't look pretty, I can't think of anything in pure C (which can get you the offset of the member, without knowing anything else about the structure. I believe the offsetofmacro is defined in this fashion.
它看起来不漂亮,我想不出纯C中的任何东西(它可以为您提供成员的偏移量,而无需了解有关结构的任何其他信息。我相信offsetof宏是以这种方式定义的。
For reference, this technique is used in the linux kernel, check out the container_ofmacro :
作为参考,此技术用于 linux 内核,请查看container_of宏:
http://lxr.free-electrons.com/source/scripts/kconfig/list.h#L18
http://lxr.free-electrons.com/source/scripts/kconfig/list.h#L18
A more elaborate explanation can be found in this article:
更详细的解释可以在这篇文章中找到:
回答by Charlie Burns
struct a foo;
printf("offset of k is %d\n", (char *)&foo.y.k - (char *)&foo);
printf("offset of i is %d\n", (char *)&foo.x.i - (char *)&foo);
foo.x.irefers to the field iin the struct xin the struct foo.
&foo.x.igives you the address of the field foo.x.i.
Similarly, &foo.y.kgives you the address of foo.y.k;
&foogives you the address of the struct foo.
foo.x.i指istructx中struct中的字段foo。
&foo.x.i为您提供该字段的地址foo.x.i。同样,&foo.y.k为您提供foo.y.k;的地址。
&foo为您提供 struct 的地址foo。
Subtracting the address of foofrom the address of foo.x.igives you the offset from footo foo.x.i.
foo从地址中减去 的地址foo.x.i为您提供从foo到的偏移量foo.x.i。
As Gangadhar says, you can use the offsetof()macro rather than the pointer arithmetic I gave. But it's good to understand the pointer arithmetic first.
正如 Gangadhar 所说,您可以使用offsetof()宏而不是我给出的指针算法。但是最好先了解指针算法。
回答by Jonathan Leffler
As already suggested, you should use the offsetof()macro from <stddef.h>, which yields the offset as a size_tvalue.
正如已经建议的那样,您应该使用offsetof()宏 from <stddef.h>,它将偏移量作为size_t值产生。
For example:
例如:
#include <stddef.h>
#include <stdio.h>
#include "struct_a.h" /* Header defining the structure in the question */
int main(void)
{
size_t off_k_y = offsetof(struct c, k);
size_t off_k_z = offsetof(struct a, y.k);
size_t off_i_x = offsetof(struct b, i);
size_t off_i_z = offsetof(struct a, x.i);
printf("k = %zu %zu; i = %zu %zu\n", off_k_y, off_k_z, off_i_x, off_i_z);
return 0;
}
Example output:
示例输出:
k = 0 8; i = 0 0
回答by clearlight
Here's a generic solution:
这是一个通用的解决方案:
#if defined(__GNUC__) && defined(__GNUC_MINOR__)
# define GNUC_PREREQ(minMajor, minMinor) \
((__GNUC__ << 16) + __GNUC_MINOR__ >= ((minMajor) << 16) + (minMinor))
#else
# define GNUC_PREREQ 0
#endif
#if GNUC_PREREQ(4, 0)
# define OFFSETOF(type, member) ((int)__builtin_offsetof(type, member))
#else
# define OFFSETOF(type, member) ((int)(intptr_t)&(((type *)(void*)0)->member) )
#endif
回答by Gurusankar Kasivinayagam
To find the offset, this is one way we can go about it.
要找到偏移量,这是我们可以解决的一种方法。
struct a{
struct b
{
int i;
float j;
}x;
struct c
{
int k;
float l;
}y;
}z;
int main(){
struct a* foo = &z;
printf("%d\n", foo); //address of z
printf("%d\n", &(foo->y)); //address of z.y
printf("%d\n", &( (&(foo->y))->k )); //address of z.y.k
int offset_k = (char*)&( (&(foo->y))->k ) - (char*)foo ;
printf("%d\n", offset_k);
return 0;
}
Output would be similar to this:
输出将类似于:
4225552 //address of z
4225560 //address of z.y
4225560 //address of z.y.k
8 //offset
In this particular case, since int i is the first member of the struct, the base address of the struct will be that of int i as well. Otherwise, you could compute the offset of int i in a similar manner.
在这种特殊情况下,由于 int i 是结构的第一个成员,因此结构的基地址也将是 int i 的基地址。否则,您可以以类似的方式计算 int i 的偏移量。
int offset_i = (char*)&( (&(foo->x))->i ) - (char*)foo; //0 in this case
NOTE: The offset will be negative or positive depending on how you define it (if it's with respect to base address or member z.y.k). Here, it is defined to be with respect to base address of struct.
注意:偏移量将是负数或正数取决于您如何定义它(如果它是关于基地址或成员 zyk)。这里,它被定义为相对于结构的基地址。

