简体   繁体   中英

Finding offset of a structure element in c

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 k so that we can find the address of int i ?

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

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/

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.xi refers to the field i in the struct x in the struct foo . &foo.xi gives you the address of the field foo.xi . Similarly, &foo.yk gives you the address of foo.yk ; &foo gives you the address of the struct foo .

Subtracting the address of foo from the address of foo.xi gives you the offset from foo to foo.xi .

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.

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

Here's a generic solution that works with both newer and older versions of GNU C:

<!-- language: C -->

#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

UPDATE: Someone asked for a usage example:

struct foo {
   int bar;
   char *baz;
}

printf("Offset of baz in struct foo = %d\n",
       OFFSETOF(foo, baz));

Would print 4, if int compiles into 4 bytes on the architecture of the machine it runs on.

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 zyk). Here, it is defined to be with respect to base address of struct.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM