Compiler error for "wrong" sized type

Discussion in 'C Programming' started by David White, May 12, 2006.

  1. David White

    David White Guest

    The size of a struct can be affected by compiler packing. Suppose you need it to be a
    specific value for some reason (e.g., in firmware). How can you get the compiler to
    generate an error for the wrong size rather than assert it at run-time? Here is one way,
    but I don't know if it's guaranteed to work on any compiler:
    1/(sizeof(struct my_struct) == correct_size);

    For me, the above produces a compile-time divide-by-zero error for the wrong size. Is
    there a better way?

    DW
     
    David White, May 12, 2006
    #1
    1. Advertising

  2. David White said:

    > The size of a struct can be affected by compiler packing. Suppose you need
    > it to be a specific value for some reason (e.g., in firmware). How can you
    > get the compiler to generate an error for the wrong size rather than
    > assert it at run-time? Here is one way, but I don't know if it's
    > guaranteed to work on any compiler: 1/(sizeof(struct my_struct) ==
    > correct_size);
    >
    > For me, the above produces a compile-time divide-by-zero error for the
    > wrong size. Is there a better way?


    Well, I don't know about "better", but I like this:

    char DetectWrongSize[(sizeof(struct my_struct) == correct_size) * 2 - 1];

    If the struct is the wrong size, this will yield a negatively sized array,
    which is illegal.

    --
    Richard Heathfield
    "Usenet is a strange place" - dmr 29/7/1999
    http://www.cpax.org.uk
    email: rjh at above domain (but drop the www, obviously)
     
    Richard Heathfield, May 12, 2006
    #2
    1. Advertising

  3. David White

    Tomás Guest

    David White posted:

    > The size of a struct can be affected by compiler packing. Suppose you
    > need it to be a specific value for some reason (e.g., in firmware). How
    > can you get the compiler to generate an error for the wrong size rather
    > than assert it at run-time? Here is one way, but I don't know if it's
    > guaranteed to work on any compiler: 1/(sizeof(struct my_struct) ==
    > correct_size);
    >
    > For me, the above produces a compile-time divide-by-zero error for the
    > wrong size. Is there a better way?
    >
    > DW



    To eliminate the padding (i.e. store each member exactly where you want it),
    you could use pointer trickery.

    For example, instead of having:

    typedef struct Monkey {
    int i;
    char b;
    int j;
    };

    You could have the following. (It's not pretty, but you could clean it up
    and give it a nice interface).


    typedef char Monkey[ 2 * sizeof(int) + 1 ];


    And then you have functions to access each member:

    void SetI( Monkey* const m, int const val )
    {
    *( (int*)m ) = val;
    }

    int GetI( const Monkey* const m )
    {
    return *( (const int*)m );
    }

    void SetB( Monkey* const m, char const val )
    {
    *( (char*)m + sizeof(int) ) = val;
    }

    char GetB( const Monkey* const m )
    {
    return *( (const char*)m + sizeof(int) );
    }

    void SetJ( Monkey* const m, int const val )
    {
    *( (int*)( (char*)m + sizeof(int) + 1 ) ) = val;
    }

    int GetJ( const Monkey* const m )
    {
    return *( (const int*)( (const char*)m + sizeof(int) + 1 ) );
    }


    -Tomás
     
    Tomás, May 12, 2006
    #3
  4. "Tomás" <> writes:
    [...]
    > To eliminate the padding (i.e. store each member exactly where you want it),
    > you could use pointer trickery.
    >
    > For example, instead of having:
    >
    > typedef struct Monkey {
    > int i;
    > char b;
    > int j;
    > };
    >
    > You could have the following. (It's not pretty, but you could clean it up
    > and give it a nice interface).
    >
    >
    > typedef char Monkey[ 2 * sizeof(int) + 1 ];
    >
    >
    > And then you have functions to access each member:

    [snip]
    > void SetJ( Monkey* const m, int const val )
    > {
    > *( (int*)( (char*)m + sizeof(int) + 1 ) ) = val;
    > }
    >
    > int GetJ( const Monkey* const m )
    > {
    > return *( (const int*)( (const char*)m + sizeof(int) + 1 ) );
    > }


    This access a misaligned int. On many systems, it will cause a trap.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
    We must do something. This is something. Therefore, we must do this.
     
    Keith Thompson, May 12, 2006
    #4
  5. David White

    Bill Pursell Guest

    Tomás wrote(in reference to structure padding):
    >
    > To eliminate the padding (i.e. store each member exactly where you want it),
    > you could use pointer trickery.
    >


    As I read that, the following thought actually fleetingly crossed my
    mind:
    "That's quite elegant, and eliminates all those annoying padding
    problems. Why did C ever bother with the syntactic sugar of structures
    and dereferencing members by name?"

    I need psychiatric assistance. :)
     
    Bill Pursell, May 12, 2006
    #5
  6. David White

    David White Guest

    Richard Heathfield wrote:
    > Well, I don't know about "better", but I like this:
    >
    > char DetectWrongSize[(sizeof(struct my_struct) == correct_size) * 2 -
    > 1];
    >
    > If the struct is the wrong size, this will yield a negatively sized
    > array, which is illegal.


    Thanks. That's an improvement. Unfortunately, our Hi-Tech compiler doesn't pick it up
    because it treats an array size of -1 as unsigned!

    DW

    P.S. A colleague is terribly disappointed to learn that an array cannot have a negative
    size. He thinks it should be allowed, with the valid index range extending from size+1 to
    zero inclusive (e.g., -9 to 0 for a size of -10). I asked him what he would expect for a
    sizeof of such an array, but he can't decide whether it should be positive or negative.
     
    David White, May 12, 2006
    #6
  7. David White

    David White Guest

    David White wrote:
    > with the
    > valid index range extending from size+1 to zero inclusive (e.g., -9
    > to 0 for a size of -10).


    Make that: size to -1 inclusive (e.g., -10 to -1 for a size of -10).

    DW
     
    David White, May 12, 2006
    #7
  8. David White wrote:
    > The size of a struct can be affected by compiler packing. Suppose you need it to be a
    > specific value for some reason (e.g., in firmware). How can you get the compiler to
    > generate an error for the wrong size rather than assert it at run-time? Here is one way,
    > but I don't know if it's guaranteed to work on any compiler:
    > 1/(sizeof(struct my_struct) == correct_size);
    >
    > For me, the above produces a compile-time divide-by-zero error for the wrong size. Is
    > there a better way?


    normally I speak against the Evil of "#prgama pack" and its ilk. Many
    compilers
    have extensions that tell the compiler to remove packing from specified
    structs.
    Such extensions are inherently non-portable and you should be very wary
    you
    don't assign packed to unpacked or vice versa. But for access to
    firmware
    especially embedded systems I think it can be justified. Embedded
    compilers
    may be more likely to support such extensions.


    --
    Nick Keighley
     
    Nick Keighley, May 12, 2006
    #8
  9. David White said:

    > I asked him what he would expect for a sizeof of such an array, but
    > he can't decide whether it should be positive or negative.


    The size of an array is equal to the number of elements times the size of
    each element. Thus, even an array with completely negative indices (were
    such an array legal) would have a positive size. Your plane doesn't
    suddenly acquire negative weight when you fly across the equator. (It may,
    however, flip upside down, depending on who wrote your fbws!)

    --
    Richard Heathfield
    "Usenet is a strange place" - dmr 29/7/1999
    http://www.cpax.org.uk
    email: rjh at above domain (but drop the www, obviously)
     
    Richard Heathfield, May 12, 2006
    #9
  10. David White

    David White Guest

    "Nick Keighley" <> wrote in message
    news:...
    >
    > normally I speak against the Evil of "#prgama pack" and its ilk. Many
    > compilers
    > have extensions that tell the compiler to remove packing from specified
    > structs.
    > Such extensions are inherently non-portable and you should be very wary
    > you
    > don't assign packed to unpacked or vice versa. But for access to
    > firmware
    > especially embedded systems I think it can be justified. Embedded
    > compilers
    > may be more likely to support such extensions.


    I also direct my compiler to use zero padding if I need to create literally
    millions of instances of a small struct, e.g., in a recursive puzzle-solving
    algorithm that generates new states exponentially and the number needed is
    unknown, and may exceed available memory. Undesirable as they may be, such
    extensions are useful or necessary in some cases (as are other quite nasty
    non-standard practices on occasion).

    DW
     
    David White, May 12, 2006
    #10
  11. David White

    Eric Sosman Guest

    David White wrote:
    > Richard Heathfield wrote:
    >
    >>Well, I don't know about "better", but I like this:
    >>
    >>char DetectWrongSize[(sizeof(struct my_struct) == correct_size) * 2 -
    >>1];
    >>
    >>If the struct is the wrong size, this will yield a negatively sized
    >>array, which is illegal.

    >
    >
    > Thanks. That's an improvement. Unfortunately, our Hi-Tech compiler doesn't pick it up
    > because it treats an array size of -1 as unsigned!
    >
    > DW
    >
    > P.S. A colleague is terribly disappointed to learn that an array cannot have a negative
    > size. He thinks it should be allowed, with the valid index range extending from size+1 to
    > zero inclusive (e.g., -9 to 0 for a size of -10). I asked him what he would expect for a
    > sizeof of such an array, but he can't decide whether it should be positive or negative.


    Wow! You're a colleague of Paul Dirac?

    Hmmm: Dirac's ideas could revolutionize memory management in
    C-- (or would it be --C?). If "no memory at all" spontaneously
    split into a chunk of allocated memory and a corresponding chunk
    of unallocated anti-memory, a program could store data in the
    allocated area without needing to call malloc(). Of course, one
    would need to be careful: pointer aliasing could cause the memory
    and anti-memory to come together and undergo mutual annihilation,
    with the resulting, er, Gamma ray constituting an implementation-
    defined signal. The task of keeping the allocation separated
    from the anti-allocation is probably best left to Maxwell's Nasal
    Demon.

    --
    Eric Sosman
    lid


    --
    Eric Sosman
    lid
     
    Eric Sosman, May 12, 2006
    #11
  12. David White wrote:
    [...]
    > P.S. A colleague is terribly disappointed to learn that an array cannot
    > have a negative size. He thinks it should be allowed, with the valid
    > index range extending from size+1 to zero inclusive (e.g., -9 to 0 for
    > a size of -10). I asked him what he would expect for a sizeof of such
    > an array, but he can't decide whether it should be positive or negative.


    http://astronomy.swin.edu.au/~pbourke/geometry/minus1.html

    --
    +-------------------------+--------------------+-----------------------------+
    | Kenneth J. Brody | www.hvcomputer.com | |
    | kenbrody/at\spamcop.net | www.fptech.com | #include <std_disclaimer.h> |
    +-------------------------+--------------------+-----------------------------+
    Don't e-mail me at: <mailto:>
     
    Kenneth Brody, May 12, 2006
    #12
  13. David White

    tedu Guest

    David White wrote:
    > Richard Heathfield wrote:
    > > Well, I don't know about "better", but I like this:
    > >
    > > char DetectWrongSize[(sizeof(struct my_struct) == correct_size) * 2 -
    > > 1];
    > >
    > > If the struct is the wrong size, this will yield a negatively sized
    > > array, which is illegal.

    >
    > Thanks. That's an improvement. Unfortunately, our Hi-Tech compiler doesn't pick it up
    > because it treats an array size of -1 as unsigned!


    does it allow multiple case statements with the same value?

    switch (0) {
    case sizeof(struct my_struct) == correct_size:
    case 0:
    }
     
    tedu, May 12, 2006
    #13
  14. David White

    S.Tobias Guest

    tedu <> wrote:
    > David White wrote:
    >> Richard Heathfield wrote:
    >> > Well, I don't know about "better", but I like this:
    >> >
    >> > char DetectWrongSize[(sizeof(struct my_struct) == correct_size) * 2 -
    >> > 1];
    >> >
    >> > If the struct is the wrong size, this will yield a negatively sized
    >> > array, which is illegal.

    >>
    >> Thanks. That's an improvement. Unfortunately, our Hi-Tech compiler doesn't pick it up
    >> because it treats an array size of -1 as unsigned!

    >
    > does it allow multiple case statements with the same value?
    >
    > switch (0) {
    > case sizeof(struct my_struct) == correct_size:
    > case 0:
    > }
    >

    Nit: a label reqires a following statement; make it:
    switch (0) {
    case sizeof(struct my_struct) == correct_size: ;
    case 0: ;
    }

    (Otherwise it's a nice trick, I liked it.)

    --
    Stan Tobias
    mailx `echo LID | sed s/[[:upper:]]//g`
     
    S.Tobias, May 12, 2006
    #14
  15. S.Tobias wrote:
    > tedu <> wrote:
    > > David White wrote:
    > >> Richard Heathfield wrote:
    > >> > Well, I don't know about "better", but I like this:
    > >> >
    > >> > char DetectWrongSize[(sizeof(struct my_struct) == correct_size) * 2 -
    > >> > 1];
    > >> >
    > >> > If the struct is the wrong size, this will yield a negatively sized
    > >> > array, which is illegal.
    > >>
    > >> Thanks. That's an improvement. Unfortunately, our Hi-Tech compiler doesn't pick it up
    > >> because it treats an array size of -1 as unsigned!

    > >
    > > does it allow multiple case statements with the same value?
    > >
    > > switch (0) {
    > > case sizeof(struct my_struct) == correct_size:
    > > case 0:
    > > }
    > >

    > Nit: a label reqires a following statement; make it:
    > switch (0) {
    > case sizeof(struct my_struct) == correct_size: ;
    > case 0: ;
    > }
    >
    > (Otherwise it's a nice trick, I liked it.)


    "case 0: ;" is a statement, so the first semicolon isn't necessary. The
    second indeed is though.
     
    =?utf-8?B?SGFyYWxkIHZhbiBExLNr?=, May 13, 2006
    #15
  16. David White

    David White Guest

    "tedu" <> wrote in message
    news:...
    > does it allow multiple case statements with the same value?


    I don't know. I'll find out next week.

    > switch (0) {
    > case sizeof(struct my_struct) == correct_size:
    > case 0:
    > }


    Good idea. Incidentally, I had a problem with this rule once. I allowed two
    different characters in encoded text to have the same meaning, e.g.,
    #define TOKEN_CHAR '#'
    #define ALT_TOKEN_CHAR 't'

    Since they have the same meaning, the switch that processed them looked like
    this:
    switch(ch)
    {
    ....
    case TOKEN_CHAR:
    case ALT_TOKEN_CHAR:
    /* process */
    break;
    ....
    }

    But in some cases I didn't want to allow both characters, so I did this:
    #define TOKEN_CHAR '#'
    #define ALT_TOKEN_CHAR '#'

    The switch then wouldn't compile, but it could have, since there's no clash.

    DW
     
    David White, May 14, 2006
    #16
    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. Yan
    Replies:
    0
    Views:
    1,161
  2. Ram
    Replies:
    0
    Views:
    2,894
  3. thechaosengine

    Oddly sized sized password textbox

    thechaosengine, Sep 15, 2005, in forum: ASP .Net
    Replies:
    1
    Views:
    599
    David Hearn
    Sep 15, 2005
  4. me

    Variable sized type

    me, Nov 5, 2004, in forum: C++
    Replies:
    3
    Views:
    304
    Arijit
    Nov 6, 2004
  5. Sanil
    Replies:
    2
    Views:
    4,821
    James Kanze
    Dec 14, 2007
Loading...

Share This Page