在c中查找结构元素的偏移量

MSB*_*MSB 24 c struct

struct a
{
    struct b
    {
        int i;
        float j;
    }x;
    struct c
    {
        int k;  
        float l;
    }y;
}z;
Run Code Online (Sandbox Code Playgroud)

任何人都可以解释我如何找到偏移量,int k以便我们可以找到地址int i

Gan*_*har 38

使用offsetof()发现,从开始的偏移z或开始x.

offsetof() - 结构构件的偏移量

概要

   #include <stddef.h>

   size_t offsetof(type, member);
Run Code Online (Sandbox Code Playgroud)

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);
   }
Run Code Online (Sandbox Code Playgroud)

如果使用GCC编译,您将在Linux上获得以下输出:

       offsets: i=0; c=4; d=8 a=16
       sizeof(struct s)=16
Run Code Online (Sandbox Code Playgroud)

  • @BlueChip 当然可以,你只需要利用人类思维的力量。`offsetof(struct a, y) + offsetof(struct c, k)` 工作得很好。 (7认同)

Cha*_*rns 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);
Run Code Online (Sandbox Code Playgroud)

foo.x.ii结构x中struct 的字段foo. &foo.x.i为您提供该字段的地址foo.x.i.同样,&foo.y.k给你的地址foo.y.k; &foo为您提供结构的地址foo.

减去的地址foo从地址foo.x.i给你从偏移foofoo.x.i.

正如Gangadhar所说,你可以使用offsetof()宏而不是我给出的指针算法.但是首先要理解指针算法是很好的.


小智 7

问题被问到已经3年了,为了完整起见,我正在添加我的答案.

获得结构成员偏移量的hacky方式就是这样

printf("%p\n", (void*)(&((struct s *)NULL)->i));
Run Code Online (Sandbox Code Playgroud)

它看起来不漂亮,我不能想到纯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/

  • @Karthik`-&gt;`运算符的优先级高于`&`运算符。因此`&(((struct s *)NULL)-&gt; i`等同于`&(((struct s *)NULL)-&gt; i)`,就像说`(((struct s *))的地址。 NULL)-&gt; i)`。 (2认同)

Jon*_*ler 5

正如已经建议的那样,您应该使用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;
}
Run Code Online (Sandbox Code Playgroud)

输出示例:

k = 0 8; i = 0 0
Run Code Online (Sandbox Code Playgroud)