Finding offset of a struct elemnet in c

If it is a simple structure, the position and size of member variables can be intuitively known.

// Differences depending on the compiler.
struct Sample {
  int sample1;    // size 4
  short sample2;  // size 2
  double sample3; // size 8
}

However, in complex structures it is difficult to calculate every day. So in that case, you can use the macro. The macro is offsetof. You can define it as below and use it.

#define OFFSETOF(type, member) &((type *)0)->member)

But standard libray or kernel has a header file(stddef.h).
This macro already defined, and see the man page to use it.

OFFSETOF(3)           Linux Programmer's Manual           OFFSETOF(3)

NAME
       offsetof - offset of a structure member

SYNOPSIS
       #include <stddef.h>

       size_t offsetof(type, member);

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

       This macro is useful because the sizes of the fields  that 
       compose a structure can vary across implementations, and 
       compilers may insert different numbers of padding bytes between 
       fields. Consequently, an element's offset is not necessarily 
       given by the sum of the sizes of the previous elements.

       A compiler error will result if member is not aligned to a byte 
       boundary (i.e., it is a bit field).

RETURN VALUE
       offsetof()  returns  the  offset  of  the given member within 
       the given type, in units of bytes.

CONFORMING TO
       POSIX.1-2001, POSIX.1-2008, C89, C99.

EXAMPLE
       On a Linux/i386 system, when compiled using the default gcc(1) 
       options, the program below produces the following output:

          $ ./a.out
          offsets: i=0; c=4; d=8 a=16
          sizeof(struct s)=16

   Program source
       #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=%zd; c=%zd; d=%zd a=%zd\n",
                   offsetof(struct s, i), offsetof(struct s, c),
                   offsetof(struct s, d), offsetof(struct s, a));
           printf("sizeof(struct s)=%zd\n", sizeof(struct s));

           exit(EXIT_SUCCESS);
       }

COLOPHON
       This page is part of release 4.04 of the Linux man-pages project.
       A description of the project, information about reporting bugs,
       and the latest version of this page, can be found at
       http://www.kernel.org/doc/man-pages/.

GNU                           2015-08-08                     OFFSETOF(3)

In the kernel, it is declared in the following path(include/linux/stddef.h), and It is used a lot in the kernel.

/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _LINUX_STDDEF_H
#define _LINUX_STDDEF_H

#include <uapi/linux/stddef.h>

#undef NULL
#define NULL ((void *)0)

enum {
	false	= 0,
	true	= 1
};

#undef offsetof
#ifdef __compiler_offsetof
#define offsetof(TYPE, MEMBER)	__compiler_offsetof(TYPE, MEMBER)
#else
#define offsetof(TYPE, MEMBER)	((size_t)&((TYPE *)0)->MEMBER)
#endif

/**
 * sizeof_field(TYPE, MEMBER)
 *
 * @TYPE: The structure containing the field of interest
 * @MEMBER: The field to return the size of
 */
#define sizeof_field(TYPE, MEMBER) sizeof((((TYPE *)0)->MEMBER))

/**
 * offsetofend(TYPE, MEMBER)
 *
 * @TYPE: The type of the structure
 * @MEMBER: The member within the structure to get the end offset of
 */
#define offsetofend(TYPE, MEMBER) \
	(offsetof(TYPE, MEMBER)	+ sizeof_field(TYPE, MEMBER))

#endif

Let’s do nice programming using the macro.