35
struct a
{
    struct b
    {
        int i;
        float j;
    }x;
    struct c
    {
        int k;  
        float l;
    }y;
}z;

谁能解释我如何找到的偏移量,int k以便我们可以找到的地址int i

4

6 回答 6

52

用于查找从 的开头或从 的开头offsetof()的偏移量。zx

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
于 2013-09-11T19:34:54.407 回答
18

自提出问题以来已经 3 年了,为了完整起见,我正在添加我的答案。

获取结构成员偏移量的hacky方法是这样的

printf("%p\n", (void*)(&((struct s *)NULL)->i));

它看起来不漂亮,我想不出纯 C 中的任何东西(它可以让你得到成员的偏移量,而不知道关于结构的任何其他内容。我相信offsetof宏是以这种方式定义的。

作为参考,这种技术在 linux 内核中使用,查看container_of宏:

http://lxr.free-electrons.com/source/scripts/kconfig/list.h#L18

更详细的解释可以在这篇文章中找到:

http://radek.io/2012/11/10/magical-container_of-macro/

于 2016-10-01T10:37:36.363 回答
10
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.ii在 structx中引用struct 中的字段foo&foo.x.i给你字段的地址foo.x.i。同样,&foo.y.k给你的地址foo.y.k; &foo给你 struct 的地址foo

foo从 的地址中减去 的地址 得到从到foo.x.i的偏移量。foofoo.x.i

正如 Gangadhar 所说,您可以使用offsetof()宏而不是我给出的指针算法。但最好先了解指针算法。

于 2013-09-11T19:15:58.727 回答
6

正如已经建议的那样,您应该使用offsetof()宏 from <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
于 2013-09-11T19:37:11.847 回答
1

要找到偏移量,这是我们可以解决的一种方法。

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

注意:偏移量将是负数或正数,具体取决于您如何定义它(如果它是关于基地址或成员 zyk)。在这里,它被定义为相对于 struct 的基地址。

于 2019-12-06T17:17:00.133 回答
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
于 2019-07-06T04:57:54.817 回答