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
?
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
offsetof(struct a, y) + offsetof(struct c, k)
works just fine. –
Dashtilut 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:
&((struct s *)NULL)->i
would work fine but ((struct s *)NULL)->i
gives segmentation fault –
Oconnell ->
operator has higher precedence than the &
operator. Thus &((struct s *)NULL)->i
is equivalent to &(((struct s *)NULL)->i)
, which is like saying take address of (((struct s *)NULL)->i)
. –
Raffo 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.
foo.x.i refers to the field i in the struct x in the struct foo
(x vs. y). –
Mccready i
, so seems to me you can stop at &foo.x.i
. –
Gaby 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.
int
in such a way as to preserve the relative magnitude of maj & min values mathematically. By doing same to both the GNU version number & major/minor values the comparisons are simpler and clearer similar to "is 3.2 > 2.5"? –
Erode 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.
© 2022 - 2024 — McMap. All rights reserved.
k
from the start ofy
, or from the start ofz
; you can find the offset ofi
from the start ofx
or from the start ofz
. However, there is essentially no guaranteed way to find the offset ofk
given the offset ofi
. You can make non-portable assumptions to come up with an answer, but why would you do that when you can come up with a portable method that doesn't involve assumptions. – Percy