struct a
{
struct b
{
int i;
float j;
}x;
struct c
{
int k;
float l;
}y;
}z;
有人可以解释我如何找到int k
的偏移量,以便我们找到int i
的地址吗?
答案 0 :(得分:35)
使用offsetof()
查找z
开头或x
开头的偏移量。
offsetof()
- 结构成员的偏移量
<强>概要强>
#include <stddef.h>
size_t offsetof(type, member);
offsetof()
返回字段成员的偏移量
结构类型的开始。
示例
#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);
}
如果使用GCC编译,您将在Linux上获得以下输出:
offsets: i=0; c=4; d=8 a=16
sizeof(struct s)=16
答案 1 :(得分:7)
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.i
引用结构i
中结构x
中的字段foo
。
&foo.x.i
为您提供字段foo.x.i
的地址。
同样,&foo.y.k
会为您提供foo.y.k
的地址;
&foo
为您提供结构foo
的地址。
从foo
的地址中减去foo.x.i
的地址会为您提供从foo
到foo.x.i
的偏移量。
正如Gangadhar所说,你可以使用offsetof()
宏而不是我给出的指针算法。但是首先要理解指针算法是很好的。
答案 2 :(得分:7)
问题问题已经过去了3年,我为了完整起见而添加了答案。
获得结构成员偏移量的hacky方式就像这样
printf("%p\n", (void*)(&((struct s *)NULL)->i));
它看起来不漂亮,我无法想到纯C中的任何东西(它可以让你获得成员的偏移,而不知道结构的任何其他内容。我相信{{1} } macro以这种方式定义。
作为参考,这个技术在linux内核中使用,请查看offsetof
宏:
http://lxr.free-electrons.com/source/scripts/kconfig/list.h#L18
本文中可以找到更详细的解释:
答案 3 :(得分:4)
如上所述,您应该使用offsetof()
中的<stddef.h>
宏,它会将偏移量生成为size_t
。
例如:
#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;
}
示例输出:
k = 0 8; i = 0 0
答案 4 :(得分:0)
这是一个通用的解决方案:
#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
答案 5 :(得分:0)
要找到偏移量,这是我们可以解决的一种方法。
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;
}
输出将类似于以下内容:
4225552 //address of z
4225560 //address of z.y
4225560 //address of z.y.k
8 //offset
在这种特殊情况下,由于int i是该结构的第一个成员,因此该结构的基址也将是int i的基址。否则,您可以以类似的方式计算int i的偏移量。
int offset_i = (char*)&( (&(foo->x))->i ) - (char*)foo; //0 in this case
注意:偏移量将为负值或正值,具体取决于您如何定义它(如果是相对于基地址或成员z.y.k)。在这里,它被定义为关于struct的基址。