Finding offset of a structure element in c

后端 未结 6 996
自闭症患者
自闭症患者 2020-12-03 09:46
struct a
{
    struct b
    {
        int i;
        float j;
    }x;
    struct c
    {
        int k;  
        float l;
    }y;
}z;

Can anybody

相关标签:
6条回答
  • 2020-12-03 10:17

    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
    
    0 讨论(0)
  • 2020-12-03 10:26

    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 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.

    0 讨论(0)
  • 2020-12-03 10:27

    Use offsetof() to find the offset from the start of z or from the start of x.

    offsetof() - offset of a structure member

    SYNOPSIS

       #include <stddef.h>
    
       size_t offsetof(type, member);
    

    offsetof() returns the offset of the field member from the start of the structure type.

    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:

           offsets: i=0; c=4; d=8 a=16
           sizeof(struct s)=16
    
    0 讨论(0)
  • 2020-12-03 10:27
    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 refers to the field i in the struct x in the struct foo. &foo.x.i gives you the address of the field foo.x.i. Similarly, &foo.y.k gives you the address of foo.y.k; &foo gives you the address of the struct foo.

    Subtracting the address of foo from the address of foo.x.i gives you the offset from foo to 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.

    0 讨论(0)
  • 2020-12-03 10:30

    It's been 3 years since the question has been asked, I'm adding my answer for the sake of completeness.

    The hacky way of getting the offset of a struct member goes like this

    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 offsetof macro is defined in this fashion.

    For reference, this technique is used in the linux kernel, check out the container_of macro :

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

    A more elaborate explanation can be found in this article:

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

    0 讨论(0)
  • 2020-12-03 10:40

    As already suggested, you should use the offsetof() macro from <stddef.h>, which yields the offset as a size_t value.

    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
    
    0 讨论(0)
提交回复
热议问题