[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.c

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

skillzero@gmail.com

9/1/2011 3:29:00 PM

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?
6 Answers

James Kuyper

9/1/2011 4:24:00 PM

0

On 09/01/2011 11:28 AM, skillzero@gmail.com wrote:
> 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).

christian.bau

9/1/2011 5:20:00 PM

0

On Sep 1, 4:28 pm, "skillz...@gmail.com" <skillz...@gmail.com> wrote:
> 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?

First, you need to give the struct used for "fields" a name so that it
can be used in offsetof. Let's say you typedef'd it as "Field". Then
you write

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

Peter Nilsson

9/1/2011 11:32:00 PM

0

"christian.bau" <christian....@cbau.wanadoo.co.uk> wrote:
> "skillz...@gmail.com" <skillz...@gmail.com> wrote:
> > 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?
>
> 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)

--
Peter

J. J. Farrell

9/1/2011 11:34:00 PM

0

James Kuyper wrote:
> On 09/01/2011 11:28 AM, skillzero@gmail.com wrote:
>> 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.

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.

Andrey Tarasevich

9/1/2011 11:38:00 PM

0

On 9/1/2011 8:28 AM, skillzero@gmail.com wrote:
>
> 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.

--
Best regards,
Andrey Tarasevich

Michael Press

9/2/2011 5:05:00 AM

0

In article
<fbfb883a-2d39-4aa4-832f-de302fac65c7@j4g2000prh.googlegroups.com>,
"skillzero@gmail.com" <skillzero@gmail.com> wrote:

> 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.

--
Michael Press