Compliant way to use offsetof for a field within a field?

S

skillzero

Is there a compliant way of getting the offset of a field within a
field? I'm mainly using this to do compile-time checks that fields are
at the offset I expect them. I'm using offsetof( NameOfStruct,
field1.field2 ) now and this works, but with some compilers, I'm
getting a warning about "Using extended field designator is an
extension". Here's an example:

typedef struct
{
uint8_t x;
uint8_t y;
struct
{
uint8_t z;

} fields;

} Test;

compile_time_assert( offsetof( Test, x ) == 0 ); // Works
compile_time_assert( offsetof( Test, y ) == 1 ); // Works
compile_time_assert( offsetof( Test, fields.z ) == 2 ); // Works, but
warns about an extension.

Is there a way to do this in a compliant way?
 
J

James Kuyper

Is there a compliant way of getting the offset of a field within a
field? I'm mainly using this to do compile-time checks that fields are
at the offset I expect them. I'm using offsetof( NameOfStruct,
field1.field2 ) now and this works, but with some compilers, I'm
getting a warning about "Using extended field designator is an
extension". Here's an example:

typedef struct
{
uint8_t x;
uint8_t y;
struct
{
uint8_t z;

} fields;

} Test;

compile_time_assert( offsetof( Test, x ) == 0 ); // Works

There's not much point in testing that one: on a conforming
implementation of C, it's guaranteed to be 0.
compile_time_assert( offsetof( Test, y ) == 1 ); // Works
compile_time_assert( offsetof( Test, fields.z ) == 2 ); // Works, but
warns about an extension.

Is there a way to do this in a compliant way?

offsetof(Test,fields) should give you the offset of z, for the same
reason that offsetof(Test,x) should give you a 0.

Of course, that answer wouldn't help if "fields" had multiple members.
The solution is to give "fields" a named type:

struct some_name {
uint8_t z;
double d;
} fields;

Then, instead of testing for offsetof(Test, fields.d), test separately
for offsetof(Test, fields) and offsetof(struct some_name, d).
 
P

Peter Nilsson

christian.bau said:
First, you need to give the struct used for "fields" a name so that
it can be used in offsetof.

To nitpick, you don't strictly need to name the struct. You can do...

offsetof(struct { uint8_t z; }, z)

But that's a maintenance nightmare.
Let's say you typedef'd it as "Field".
Then you write

offsetof (Test, fields) + offsetof (Fields, z) == 2.

ITYM offsetof (Field, z)
 
J

J. J. Farrell

James said:
There's not much point in testing that one: on a conforming
implementation of C, it's guaranteed to be 0.

One common reason for testing that is to protect against someone later
modifying the structure by putting something in front of x. It's
certainly not needed if the purpose is to check that assumptions about
padding are valid; but if the purpose is to check that certain fields in
the structure match certain externally defined data, then it protects
against changes by people who don't understand all the implications of
what they're doing.
 
A

Andrey Tarasevich

typedef struct
{
uint8_t x;
uint8_t y;
struct
{
uint8_t z;

} fields;

} Test;

compile_time_assert( offsetof( Test, x ) == 0 ); // Works
compile_time_assert( offsetof( Test, y ) == 1 ); // Works
compile_time_assert( offsetof( Test, fields.z ) == 2 ); // Works, but
warns about an extension.

Is there a way to do this in a compliant way?

What compiler are you using? Are you sure you are not compiling your
code as C++ code?

The `offsetof( Test, fields.z )` _is_ the compliant way in C. There are
no extensions of any kind involved here.

The specification of `offsetof` is C language only requires that
`&object.member_designator` be an address constant (for some imagginary
static object `object`). There's no requirement for the
'member_designator' to designate the immediate member of the structure.
It is perfectly allowed to use `offsetof` with "deeper" members of the
struct type.
 
M

Michael Press

Is there a compliant way of getting the offset of a field within a
field? I'm mainly using this to do compile-time checks that fields are
at the offset I expect them. I'm using offsetof( NameOfStruct,
field1.field2 ) now and this works, but with some compilers, I'm
getting a warning about "Using extended field designator is an
extension". Here's an example:

typedef struct
{
uint8_t x;
uint8_t y;
struct
{
uint8_t z;

} fields;

} Test;

compile_time_assert( offsetof( Test, x ) == 0 ); // Works
compile_time_assert( offsetof( Test, y ) == 1 ); // Works
compile_time_assert( offsetof( Test, fields.z ) == 2 ); // Works, but
warns about an extension.

Is there a way to do this in a compliant way?

Set each structure field to distinct bit patterns.
Find sizeof(Test).
Dump the the entire struct into a buffer with memcpy or some such.
Analyze the contents of the buffer.

This method is known as extispicy.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,756
Messages
2,569,540
Members
45,025
Latest member
KetoRushACVFitness

Latest Threads

Top