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

Discussion in 'C Programming' started by skillzero@gmail.com, Sep 1, 2011.

  1. Guest

    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?
     
    , Sep 1, 2011
    #1
    1. Advertising

  2. James Kuyper Guest

    On 09/01/2011 11:28 AM, 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).
     
    James Kuyper, Sep 1, 2011
    #2
    1. Advertising

  3. "christian.bau" <> wrote:
    > "" <> 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
     
    Peter Nilsson, Sep 2, 2011
    #3
  4. James Kuyper wrote:
    > On 09/01/2011 11:28 AM, 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.
     
    J. J. Farrell, Sep 2, 2011
    #4
  5. On 9/1/2011 8:28 AM, 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
     
    Andrey Tarasevich, Sep 2, 2011
    #5
  6. In article
    <>,
    "" <> 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
     
    Michael Press, Sep 2, 2011
    #6
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. J44xm
    Replies:
    12
    Views:
    650
    J44xm
    Feb 18, 2005
  2. Hiroki Horiuchi

    g++ "offsetof" problem

    Hiroki Horiuchi, Nov 25, 2003, in forum: C++
    Replies:
    5
    Views:
    6,613
    red floyd
    Nov 25, 2003
  3. Tony Johansson

    offsetof

    Tony Johansson, Dec 16, 2004, in forum: C++
    Replies:
    1
    Views:
    461
    Alf P. Steinbach
    Dec 16, 2004
  4. Tony Johansson

    More offsetof

    Tony Johansson, Dec 16, 2004, in forum: C++
    Replies:
    3
    Views:
    520
    Mike Wahler
    Dec 18, 2004
  5. Replies:
    18
    Views:
    578
    James Kuyper
    Nov 10, 2007
Loading...

Share This Page