Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c > #9819 > unrolled thread

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

Started by"skillzero@gmail.com" <skillzero@gmail.com>
First post2011-09-01 08:28 -0700
Last post2011-09-01 22:05 -0700
Articles 7 — 7 participants

Back to article view | Back to comp.lang.c


Contents

  Compliant way to use offsetof for a field within a field? "skillzero@gmail.com" <skillzero@gmail.com> - 2011-09-01 08:28 -0700
    Re: Compliant way to use offsetof for a field within a field? James Kuyper <jameskuyper@verizon.net> - 2011-09-01 12:23 -0400
      Re: Compliant way to use offsetof for a field within a field? "J. J. Farrell" <jjf@bcs.org.uk> - 2011-09-02 00:34 +0100
    Re: Compliant way to use offsetof for a field within a field? "christian.bau" <christian.bau@cbau.wanadoo.co.uk> - 2011-09-01 10:19 -0700
      Re: Compliant way to use offsetof for a field within a field? Peter Nilsson <airia@acay.com.au> - 2011-09-01 16:31 -0700
    Re: Compliant way to use offsetof for a field within a field? Andrey Tarasevich <andreytarasevich@hotmail.com> - 2011-09-01 16:38 -0700
    Re: Compliant way to use offsetof for a field within a field? Michael Press <rubrum@pacbell.net> - 2011-09-01 22:05 -0700

#9819 — Compliant way to use offsetof for a field within a field?

From"skillzero@gmail.com" <skillzero@gmail.com>
Date2011-09-01 08:28 -0700
SubjectCompliant way to use offsetof for a field within a field?
Message-ID<fbfb883a-2d39-4aa4-832f-de302fac65c7@j4g2000prh.googlegroups.com>
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?

[toc] | [next] | [standalone]


#9825

FromJames Kuyper <jameskuyper@verizon.net>
Date2011-09-01 12:23 -0400
Message-ID<4E5FB187.7030305@verizon.net>
In reply to#9819
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).

[toc] | [prev] | [next] | [standalone]


#9850

From"J. J. Farrell" <jjf@bcs.org.uk>
Date2011-09-02 00:34 +0100
Message-ID<j3p4pm$7eq$1@dont-email.me>
In reply to#9825
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.

[toc] | [prev] | [next] | [standalone]


#9828

From"christian.bau" <christian.bau@cbau.wanadoo.co.uk>
Date2011-09-01 10:19 -0700
Message-ID<9a909a63-8328-49b8-a0a4-bdf34c67ab06@k9g2000vbd.googlegroups.com>
In reply to#9819
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.

[toc] | [prev] | [next] | [standalone]


#9848

FromPeter Nilsson <airia@acay.com.au>
Date2011-09-01 16:31 -0700
Message-ID<453f9879-47e4-4429-9587-293c04112340@e20g2000prn.googlegroups.com>
In reply to#9828
"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

[toc] | [prev] | [next] | [standalone]


#9852

FromAndrey Tarasevich <andreytarasevich@hotmail.com>
Date2011-09-01 16:38 -0700
Message-ID<j3p4vr$8ah$1@dont-email.me>
In reply to#9819
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

[toc] | [prev] | [next] | [standalone]


#9871

FromMichael Press <rubrum@pacbell.net>
Date2011-09-01 22:05 -0700
Message-ID<rubrum-2179E2.22050301092011@news.albasani.net>
In reply to#9819
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

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.c


csiph-web