Treating 'char' Structure Members as Contiguous Bytes

Discussion in 'C Programming' started by Martin, Feb 7, 2008.

  1. Martin

    Martin Guest

    The following compiles cleanly on gcc3.0.4 using -W -Wall -ansi -
    pedantic. Lint gives this warning:
    _
    p_member_09 = p_start + OFFSET_TO_MEMBER_09;
    t_offset.c 27 Warning 416: creation of out-of-bounds pointer (33
    beyond end of data) by operator ptr+int' [Reference: file t_offset.c:
    lines 26, 27]

    The underscore Lint uses to indicate the point of warning is over the
    'O' in OFFSET_TO_MEMBER_09.

    My question is this. Is the technique used here well-defined and safe
    practice?


    typedef unsigned char uchar;

    struct byte_array {
    uchar member_01;
    uchar member_02[8];
    uchar member_03[2];
    uchar member_04[2];
    uchar member_05[8];
    uchar member_06[2];
    uchar member_07[2];
    uchar member_08[8];
    uchar member_09[2];
    uchar member_10[2];
    };

    struct byte_array byte_array;

    #define OFFSET_TO_MEMBER_06 21
    #define OFFSET_TO_MEMBER_09 33

    int main( void )
    {
    uchar *p_start;
    uchar *p_member_09;

    p_start = &byte_array.member_01;
    p_member_09 = p_start + OFFSET_TO_MEMBER_09;

    return 0;
    }
     
    Martin, Feb 7, 2008
    #1
    1. Advertising

  2. Martin

    Richard Bos Guest

    Martin <> wrote:

    > The following compiles cleanly on gcc3.0.4 using -W -Wall -ansi -
    > pedantic. Lint gives this warning:
    > _
    > p_member_09 = p_start + OFFSET_TO_MEMBER_09;
    > t_offset.c 27 Warning 416: creation of out-of-bounds pointer (33
    > beyond end of data) by operator ptr+int' [Reference: file t_offset.c:
    > lines 26, 27]


    > My question is this. Is the technique used here well-defined and safe
    > practice?


    I'll let others figure out the exact safety of the technique you use -
    my first instincts say that it's undefined behaviour in theory, but very
    unlikely to break - and suggest that regardless of the outcome, you
    switch to a guaranteed safe technique: use offsetof(). You'll need to
    #include <stddef.h>.

    Richard
     
    Richard Bos, Feb 7, 2008
    #2
    1. Advertising

  3. Martin

    Thad Smith Guest

    Martin wrote:
    > The following compiles cleanly on gcc3.0.4 using -W -Wall -ansi -
    > pedantic. Lint gives this warning:
    > _
    > p_member_09 = p_start + OFFSET_TO_MEMBER_09;
    > t_offset.c 27 Warning 416: creation of out-of-bounds pointer (33
    > beyond end of data) by operator ptr+int' [Reference: file t_offset.c:
    > lines 26, 27]
    >
    > The underscore Lint uses to indicate the point of warning is over the
    > 'O' in OFFSET_TO_MEMBER_09.
    >
    > My question is this. Is the technique used here well-defined and safe
    > practice?
    >
    >
    > typedef unsigned char uchar;
    >
    > struct byte_array {
    > uchar member_01;
    > uchar member_02[8];
    > uchar member_03[2];
    > uchar member_04[2];
    > uchar member_05[8];
    > uchar member_06[2];
    > uchar member_07[2];
    > uchar member_08[8];
    > uchar member_09[2];
    > uchar member_10[2];
    > };
    >
    > struct byte_array byte_array;
    >
    > #define OFFSET_TO_MEMBER_06 21
    > #define OFFSET_TO_MEMBER_09 33
    >
    > int main( void )
    > {
    > uchar *p_start;
    > uchar *p_member_09;
    >
    > p_start = &byte_array.member_01;
    > p_member_09 = p_start + OFFSET_TO_MEMBER_09;
    >
    > return 0;
    > }


    It is not defined because the struct may have padding between members
    (although it is unlikely when the members are arrays of unsigned char).

    You can instead write
    p_member_09 = byte_array.member_09;
    or
    p_member_09 = (uchar*)byte_array + offsetof (struct byte_array, member_09);


    --
    Thad
     
    Thad Smith, Feb 7, 2008
    #3
  4. Martin wrote:
    > ...
    > My question is this. Is the technique used here well-defined and safe
    > practice?
    > ...


    From the pedantic point of view of the standard C language, this
    technique is not safe. It caused undefined behavior. Just a mere attempt
    to add more than 1 to '&byte_array.member_01' is already UB.

    Now, somewhere in the low level platform-specific code this techniques
    might be considered acceptable, but, once again, you have to know what
    your are doing and be ready for the unexpected. It might make sense to
    add a bunch of STATIC_ASSERTs that might look as follows

    STATIC_ASSERT(OFFSET_TO_MEMBER_06 == offsetof(byte_array, member_09))

    and so on (look up STATIC_ASSERT on Google for possible implementations).

    --
    Best regards,
    Andrey Tarasevich
     
    Andrey Tarasevich, Feb 7, 2008
    #4
  5. Martin

    Army1987 Guest

    Martin wrote:
    [...]
    > typedef unsigned char uchar;
    >
    > struct byte_array {
    > uchar member_01;
    > uchar member_02[8];

    [...]
    > uchar member_10[2];
    > };
    >
    > struct byte_array byte_array;
    >
    > #define OFFSET_TO_MEMBER_06 21
    > #define OFFSET_TO_MEMBER_09 33

    #include <stddef.h>
    >
    > int main( void )
    > {
    > uchar *p_start;
    > uchar *p_member_09;
    >
    > p_start = &byte_array.member_01;
    > p_member_09 = p_start + OFFSET_TO_MEMBER_09;

    Why not p_start + offsetof(byte_array, member_09)?
    [...]


    --
    Army1987 (Replace "NOSPAM" with "email")
     
    Army1987, Feb 8, 2008
    #5
  6. Martin

    Martin Guest

    My thanks to you all for your responses.

    Although it's a perfectly reasonable assumption that the code I posted
    was mine, it is in fact code I am maintaining and I would not have
    written it that way. I posted to confirm what I already suspected -
    that it evoked undefined behaviour. Andrey Tarasevich put it
    succinctly, and Richard Bos has confirmed what is happening in
    practice - the code works. That is unfortunate because there is no
    motivation to fix it by those that can authorise such a thing. I can
    make a unilateral decision to do so, but they then would have to be
    willing to merge my changes into their code.

    --
    Martin
     
    Martin, Feb 11, 2008
    #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. Olumide
    Replies:
    9
    Views:
    1,919
    Dan Pop
    Nov 30, 2004
  2. Replies:
    5
    Views:
    549
    Flash Gordon
    Apr 9, 2006
  3. lovecreatesbeauty
    Replies:
    1
    Views:
    1,058
    Ian Collins
    May 9, 2006
  4. Replies:
    8
    Views:
    506
    Bob Hairgrove
    Apr 10, 2006
  5. chachi
    Replies:
    2
    Views:
    413
    Aaron Brady
    Nov 14, 2008
Loading...

Share This Page