views:

453

answers:

3

Is there a way of finding the offset of a member of a structure at compile-time? I wish to create a constant containing the offset of a structure member. In the following code the offsetof() macro works in the first printf statement. However, the use in line 10 to declare 'ofs' generates the error "Cannot resolve '->' operator as a constant expression". Is there any other way of doing it?

struct MyStruct
{
   unsigned long lw;
   unsigned char c[5];
   int i;
   int j;
   unsigned long last;
};

const int ofs = offsetof(struct MyStruct, i);  // This line in error

int main(void)
{
   printf("Offset of c = %d.\n", offsetof(struct MyStruct, c) );
   printf("Offset of i = %d.\n", ofs );
   return 0;
}
+4  A: 

It compiles without warning here with g++ 4, after I add the proper #includes.

Are you #including stddef.h? offsetof() is a macro, not a built-in keyword in C.

If that doesn't fix it, try making the constant static, to confine it to the module. That might make the compiler happy.

Warren Young
+6  A: 

The offsetof() macro is a compile-time construct. There is no standard-compliant way to define it, but every compiler must have some way of doing it.

One example would be:

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

While not being a compile-time construct technically (see comments by user "litb"), every compiler must have at least one such expression that it is able to resolve at compile time, which is exactly what offsetof() is defined to in <stddef.h>.

There is probably some other error to your code - a missing include of <stddef.h>, or some other thing irritating your compiler.

DevSolar
That's not what he means with "compile time", of course. You show a construct that doesn't use a library function, but that doesn't mean it evaluates to a compile time value. Whether or not code is actually emitted is irrelevant of course - the C draft says "An arithmetic constant expression shall have arithmetic type and shall only have operands that are integer constants, floating constants, enumeration constants, character constants, and sizeof expressions.". Pointers are not allowed in the mix.
Johannes Schaub - litb
`offsetof` is a compile time construct and evaluates to a integer constant expression, but your example implementation doesn't.
Johannes Schaub - litb
There is *NO* way in the language to define offsetof() as something that evaluates to an integer constant expression. There is *NO* way to define it without using pointers. No matter what you do, you will always rely on a compiler builtin and / or the capability of the compiler to optimize your expression appropriately. Check Wikipedia on offsetof, or any open-source C library. So, while you are technically correct on the definition of integer constant expressions (and I adapt my wording), you are wrong in pointing a finger at my example implementation.
DevSolar
For what it's worth, above implementation is identical to the one in (glibc) ./resolv/nss_dns/dns-network.c.
DevSolar
I pointed my finger not only at your example implementation, but your example implementation with your "see, all compile time" attached to it. I'm aware that there may be defective implementations of that macro (and the questioner most probably just hit such a defective implementation). I can't comment on that c-files macro, but if it's using such a thing and claims to be a portable replacement of "offsetof" (i doubt - because the file looks "official"), then it's just wrong - but it may still work for *its* purpose. GCC's implementation for example just calls "__builtin_offsetof".
Johannes Schaub - litb
That said, i will remove my -1 because you manly handled the inconsistency. In any case, i don't want to read wikipedia - there is enough nonsense written about C and C++ on it - i'm not ready to become infected :)
Johannes Schaub - litb
Just to point it out again: There is *NO* way to implement offsetof in a *portable* way. It's a tricky corner of the language standard.
DevSolar
+2  A: 

If you have a #include <stddef.h> as I assume (the error message you cite without would be meaningless), it is a bug in your compiler. offsetof result is an integer constant expression in C99 as well as in C90.

AProgrammer