I'm finding I'm spending a lot of time trying to determine member offsets of structures while debugging. I was wondering if there was a quick way to determine the offset of a member within a large structure at compile time. (Note: I know several ways of creating compile time assertions that an offset is in a given range, and I can do a binary search for the correct value, but I'm looking for something more efficient). I'm using a fairly recent version of gcc
to compile C code.
offsetof is what you want for this and it compile time. The C99 draft standard section 7.17
Common definitions paragraph 3 says:
offsetof(type, member-designator)
which expands to an integer constant expression that has type size_t, the value of which is the offset in bytes [...]
the man pages linked above has the following sample code, which demonstrates it's usage:
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));
sample output, which may vary:
offsets: i=0; c=4; d=8 a=16
sizeof(struct s)=16
For reference constant expressions are covered in section 6.6
Constant expressions and paragraph 2 says:
A constant expression can be evaluated during translation rather than runtime, and accordingly may be used in any place that a constant may be.
Update
After clarification from the OP I came up with a new methods using -O0 -fverbose-asm -S
and grep, code is as follows:
#include <stddef.h>
struct s {
int i;
char c;
double d;
char a[];
};
int main()
{
int offsetArray[4] = { offsetof(struct s, i ), offsetof( struct s, c ), offsetof(struct s, d ), offsetof(struct s, a ) } ;
return 0 ;
}
build using:
gcc -x c -std=c99 -O0 -fverbose-asm -S main.cpp && cat main.s | grep offsetArray
sample output (live example):
movl $0, -16(%rbp) #, offsetArray
movl $4, -12(%rbp) #, offsetArray
movl $8, -8(%rbp) #, offsetArray
movl $16, -4(%rbp) #, offsetArray
Ok, answering my own question here: Note: I'm looking to determine the offset at compile time, that is, I don't want to have to run the code (I can also compile just the files I need, and not the whole system): The following can be cut and paste for those who are interested:
#include <stddef.h>
#define offsetof_ct(structname, membername) \
void ___offset_##membername ## ___(void) { \
volatile char dummy[10000 + offsetof(structname, membername) ]; \
dummy[0]=dummy[0]; \
}
struct x {
int a[100];
int b[20];
int c[30];
};
offsetof_ct(struct x,a);
offsetof_ct(struct x,b);
offsetof_ct(struct x,c);
And then run:
~/tmp> gcc tst.c -Wframe-larger-than=1000
tst.c: In function ‘___offset_a___’:
tst.c:16:1: warning: the frame size of 10000 bytes is larger than 1000 bytes
tst.c: In function ‘___offset_b___’:
tst.c:17:1: warning: the frame size of 10400 bytes is larger than 1000 bytes
tst.c: In function ‘___offset_c___’:
tst.c:18:1: warning: the frame size of 10480 bytes is larger than 1000 bytes
/usr/lib/gcc/x86_64-redhat-linux/4.5.1/../../../../lib64/crt1.o: In function `_start':
(.text+0x20): undefined reference to `main'
collect2: ld returned 1 exit status
I then subtract 10000 to get the offset. Note: I tried adding #pragma GCC diagnostic warning "-Wframe-larger-than=1000"
into the file, but it didn't like it, so it'll have to be specified on the command line.
John
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With