How two check struct size at compile time

Discussion in 'C Programming' started by FTSoJ, May 20, 2005.

  1. FTSoJ

    FTSoJ Guest

    On a file A.c I define the structure T1
    typedef struct {
    int dummy;
    int age;
    char lastname [128];
    char firstname[128];
    } T1_user;


    On a file B.c I define a strcuture T2

    typedef struct {
    int id;
    int age;
    char dummy[256]
    } T2_id;

    I would like to generate an error during compilation if sizeof (T1)
    differ from sizeof(T2).
    I tried
    #if sizeof(T2_id) != sizeof(T1_user)
    #error "Size of T1_user differ from T2_id, compile abort!"
    #endif


    But it fails on metrowerks as on GCC.

    This is a sample, in real T1 from Tn are unions and I would like to
    guaranty that interprocess exchange can't lead to buffer overflow if one
    Tn type is modified in the future.

    Regards,

    - Fran├žois -
     
    FTSoJ, May 20, 2005
    #1
    1. Advertising

  2. FTSoJ

    S.Tobias Guest

    FTSoJ <> wrote:

    > #if sizeof(T2_id) != sizeof(T1_user)
    > #error "Size of T1_user differ from T2_id, compile abort!"
    > #endif


    Preprocessor will not do it, you have to trick the compiler
    to do it for you.
    Google for "CCASSERT", a handy invention in this group.

    --
    Stan Tobias
    mailx `echo LID | sed s/[[:upper:]]//g`
     
    S.Tobias, May 20, 2005
    #2
    1. Advertising

  3. In article <428d750b$0$11684$>,
    FTSoJ <> wrote:

    > On a file A.c I define the structure T1
    > typedef struct {
    > int dummy;
    > int age;
    > char lastname [128];
    > char firstname[128];
    > } T1_user;
    >
    >
    > On a file B.c I define a strcuture T2
    >
    > typedef struct {
    > int id;
    > int age;
    > char dummy[256]
    > } T2_id;
    >
    > I would like to generate an error during compilation if sizeof (T1)
    > differ from sizeof(T2).
    > I tried
    > #if sizeof(T2_id) != sizeof(T1_user)
    > #error "Size of T1_user differ from T2_id, compile abort!"
    > #endif


    Try these two:

    char* p = 0;
    char* q = 1;

    One compiles, the other doesn't. The reason is that 0 is a "null pointer
    constant" and will be converted to a null pointer when needed, 1 isn't
    and assigning an int to a char* is not allowed.

    Say you want to verify at compile time that sizeof (T2_id) == sizeof
    (T1_user). The expression

    sizeof (T2_id) != sizeof (T1_user)

    is 0 if the sizes are the same, and 1 if the sizes are different.
    Therefore

    char* p = (sizeof (T2_id) != sizeof (T1_user));

    will compile if the sizes are the same and won't compile if the sizes
    are different. Now pack that into a nice macro for readability, and
    that's it.
     
    Christian Bau, May 20, 2005
    #3
  4. FTSoJ

    jacob navia Guest

    Christian Bau wrote:
    > In article <428d750b$0$11684$>,
    > FTSoJ <> wrote:
    >
    >
    >>On a file A.c I define the structure T1
    >>typedef struct {
    >> int dummy;
    >> int age;
    >> char lastname [128];
    >> char firstname[128];
    >>} T1_user;
    >>
    >>
    >>On a file B.c I define a strcuture T2
    >>
    >>typedef struct {
    >> int id;
    >> int age;
    >> char dummy[256]
    >>} T2_id;
    >>
    >>I would like to generate an error during compilation if sizeof (T1)
    >>differ from sizeof(T2).
    >>I tried
    >>#if sizeof(T2_id) != sizeof(T1_user)
    >>#error "Size of T1_user differ from T2_id, compile abort!"
    >>#endif

    >
    >
    > Try these two:
    >
    > char* p = 0;
    > char* q = 1;
    >
    > One compiles, the other doesn't. The reason is that 0 is a "null pointer
    > constant" and will be converted to a null pointer when needed, 1 isn't
    > and assigning an int to a char* is not allowed.
    >
    > Say you want to verify at compile time that sizeof (T2_id) == sizeof
    > (T1_user). The expression
    >
    > sizeof (T2_id) != sizeof (T1_user)
    >
    > is 0 if the sizes are the same, and 1 if the sizes are different.
    > Therefore
    >
    > char* p = (sizeof (T2_id) != sizeof (T1_user));
    >
    > will compile if the sizes are the same and won't compile if the sizes
    > are different. Now pack that into a nice macro for readability, and
    > that's it.


    VERY clever. Neever thought about it!
     
    jacob navia, May 20, 2005
    #4
  5. FTSoJ

    Alex Fraser Guest

    "FTSoJ" <> wrote in message
    news:428d750b$0$11684$...
    [snip]
    > I would like to generate an error during compilation if sizeof (T1)
    > differ from sizeof(T2).
    > I tried
    > #if sizeof(T2_id) != sizeof(T1_user)
    > #error "Size of T1_user differ from T2_id, compile abort!"
    > #endif
    >
    > But it fails on metrowerks as on GCC.
    >
    > This is a sample, in real T1 from Tn are unions and I would like to
    > guaranty that interprocess exchange can't lead to buffer overflow if one
    > Tn type is modified in the future.


    Instead of trying to ensure they are all the same size, perhaps you could
    make the code insensitive to different sizes - for example, by putting them
    all in a union and using that as the unit for "interprocess exchange".

    Alex
     
    Alex Fraser, May 20, 2005
    #5
  6. FTSoJ

    Jason Curl Guest

    FTSoJ wrote:
    > On a file A.c I define the structure T1
    > typedef struct {
    > int dummy;
    > int age;
    > char lastname [128];
    > char firstname[128];
    > } T1_user;
    >
    >
    > On a file B.c I define a strcuture T2
    >
    > typedef struct {
    > int id;
    > int age;
    > char dummy[256]
    > } T2_id;
    >
    > I would like to generate an error during compilation if sizeof (T1)
    > differ from sizeof(T2).
    > I tried
    > #if sizeof(T2_id) != sizeof(T1_user)
    > #error "Size of T1_user differ from T2_id, compile abort!"
    > #endif
    >
    >
    > But it fails on metrowerks as on GCC.
    >
    > This is a sample, in real T1 from Tn are unions and I would like to
    > guaranty that interprocess exchange can't lead to buffer overflow if one
    > Tn type is modified in the future.


    The only solutions I've seen in API's is to pass the length of the
    structure at the beginning of the structure, and use run-time checking
    to protect against overflows.

    >
    > Regards,
    >
    > - Fran├žois -
     
    Jason Curl, May 20, 2005
    #6
  7. FTSoJ

    Old Wolf Guest

    Re: How two check struct size at compile time

    Christian Bau wrote:
    > >
    > > I would like to generate an error during compilation if
    > > sizeof (T1) differ from sizeof(T2).

    >
    > char* p = (sizeof (T2_id) != sizeof (T1_user));
    >
    > will compile if the sizes are the same and won't compile if the
    > sizes are different. Now pack that into a nice macro for
    > readability, and that's it.


    Another of the many options is:

    typedef char p[ (sizeof(T2) == sizeof(T1)) ? 1 : -1];

    because you can't have an array type with negative bound.
    Also this option won't actually declare a variable and
    potentially use up memory, and is more likely (IME) to
    cause the compiler to stop compilation.

    If you make this a macro, you probably want to roll
    __LINE__ into it, otherwise if you use the macro twice in the
    same scope, the compiler will complain about a re-declared
    variable.

    For a pre-existing solution, check out STATIC_ASSERT in the
    preprocessor section of http://www.boost.org/
     
    Old Wolf, May 20, 2005
    #7
    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. Chris Fogelklou
    Replies:
    36
    Views:
    1,405
    Chris Fogelklou
    Apr 20, 2004
  2. Replies:
    5
    Views:
    556
    Flash Gordon
    Apr 9, 2006
  3. John Smith
    Replies:
    4
    Views:
    964
    Rolf Magnus
    Jan 5, 2006
  4. Nagaraj
    Replies:
    1
    Views:
    888
    Lionel B
    Mar 1, 2007
  5. Carter
    Replies:
    2
    Views:
    517
    Carter
    Mar 4, 2009
Loading...

Share This Page