#if constant expression

Discussion in 'C Programming' started by kerravon, Dec 10, 2007.

  1. kerravon

    kerravon Guest

    According to 6.8 of C90, #if takes a constant expression.

    According to 6.4 of C90, the sizeof operator is part of a constant
    expression.

    Why then do most of my compilers barf on this?

    #include <stdio.h>

    #if sizeof(int) >= 4
    #define XXX "big"
    #else
    #define XXX "small"
    #endif

    int main(void)
    {
    printf("hello %s\n", XXX);
    return (0);
    }

    They barf on the "#if sizeof ..." line.

    They explicitly say that I can't use sizeof in a #if

    So which bit of the standard did I miss?

    BFN. Paul.
     
    kerravon, Dec 10, 2007
    #1
    1. Advertising

  2. kerravon

    vicks Guest

    > #include <stdio.h>
    >
    > #if sizeof(int) >= 4
    > #define XXX "big"
    > #else
    > #define XXX "small"
    > #endif
    >
    > int main(void)
    > {
    > printf("hello %s\n", XXX);
    > return (0);
    >
    > }
    >

    [code snnipet...]
    > So which bit of the standard did I miss?



    Well I think that #if can be used only with the Macros(who gets
    replaced with contant expressions at compile time) since sizeof gets
    resolved at run time I dont think it's good idea to use sizeof with
    #if!!

    Regards
    Vikas Gupta
     
    vicks, Dec 10, 2007
    #2
    1. Advertising

  3. kerravon

    James Kuyper Guest

    kerravon wrote:
    > According to 6.8 of C90, #if takes a constant expression.
    >
    > According to 6.4 of C90, the sizeof operator is part of a constant
    > expression.
    >
    > Why then do most of my compilers barf on this?
    >
    > #include <stdio.h>
    >
    > #if sizeof(int) >= 4
    > #define XXX "big"
    > #else
    > #define XXX "small"
    > #endif
    >
    > int main(void)
    > {
    > printf("hello %s\n", XXX);
    > return (0);
    > }
    >
    > They barf on the "#if sizeof ..." line.
    >
    > They explicitly say that I can't use sizeof in a #if
    >
    > So which bit of the standard did I miss?
    >
    > BFN. Paul.


    I don't have a copy of C90; but I suspect that this is not an area where
    the differences between C90 and C99 matter. Section 6.10.1p4 of
    n1256.pdf says

    "After all replacements due to macro expansion and the *defined* unary
    operator have been performed, all remaining identifiers (including those
    lexically identical to keywords) are replaced with the pp-number 0, "

    I believe that this applies to both 'sizeof' and 'int' in your example.
    As a result, it becomes:

    #if 0(0) >= 4

    which explains why it fails.
     
    James Kuyper, Dec 10, 2007
    #3
  4. vicks <> wrote in news:d485a4a6-dd4a-492e-a00b-
    :

    > Well I think that #if can be used only with the Macros(who gets
    > replaced with contant expressions at compile time) since sizeof gets
    > resolved at run time I dont think it's good idea to use sizeof with
    > #if!!



    sizeof yields a compile-time constant, and is very much _not_ evaluated at
    runtime.

    --
    Tomás Ó hÉilidhe
     
    Tomás Ó hÉilidhe, Dec 10, 2007
    #4
  5. kerravon

    pete Guest

    kerravon wrote:
    >
    > According to 6.8 of C90, #if takes a constant expression.
    >
    > According to 6.4 of C90, the sizeof operator is part of a constant
    > expression.


    The preprocessor can't read keywords.


    ISO/IEC 9899: 1990
    6.8.1 Conditional inclusion
    Constraints

    identifiers (including those lexically identical to keywords)
    are interpreted as described below;83

    83 Because the controlling constant expression
    is evaluated during translation phase 4,
    all identifiers either are or are not macro names
    — there simply are no keywords, enumeration constants, etc.


    --
    pete
     
    pete, Dec 10, 2007
    #5
  6. kerravon

    quarkLore Guest

    On Dec 10, 8:11 am, pete <> wrote:
    > kerravon wrote:
    >
    > > According to 6.8 of C90, #if takes a constant expression.

    >
    > > According to 6.4 of C90, the sizeof operator is part of a constant
    > > expression.

    >
    > The preprocessor can't read keywords.
    >
    > ISO/IEC 9899: 1990
    > 6.8.1 Conditional inclusion
    > Constraints
    >
    > identifiers (including those lexically identical to keywords)
    > are interpreted as described below;83
    >
    > 83 Because the controlling constant expression
    > is evaluated during translation phase 4,
    > all identifiers either are or are not macro names
    > -- there simply are no keywords, enumeration constants, etc.
    >
    > --
    > pete


    #if is for preprocessor, sizeof is a compile time operator but not
    handled at preprocessing stage. If you have gcc put sizeof in your
    code and run gcc -E <soure filename> it should give you the
    preprocessor output and sizeof would remain as it is.
     
    quarkLore, Dec 10, 2007
    #6
  7. In article
    <>,
    kerravon <> wrote:

    > Why then do most of my compilers barf on this?


    #include <stdio.h>
    #if sizeof(int) >= 4
    #define XXX "big"
    #else
    #define XXX "small"
    #endif
    int main(void)
    {
    printf("hello %s\n", XXX);
    return (0);
    }

    One way to see this is that sizeof is not usable in the proprocessor, which has no
    knowledge of types. There is a solution, though

    #include <stdio.h>
    #define XXX (sizeof(int) >= 4 ? "big" : "small")
    int main(void)
    {
    printf("hello %s\n", XXX);
    return (0);
    }



    If you want to check at compile time that int is big:


    /* cause a compile-time error if x is 0 */
    #define CompileAssert(x) do{typedef struct{char f[(x)?1:-1];}assertion_failure;}while(0) /* compile time assertion failure */

    #include <stdio.h>
    int main(void)
    {
    CompileAssert(sizeof(int) >= 4);
    puts("hello big");
    return (0);
    }


    Francois Grieu
     
    Fancois Grieu, Dec 10, 2007
    #7
  8. pete <> writes:
    > kerravon wrote:
    >>
    >> According to 6.8 of C90, #if takes a constant expression.
    >>
    >> According to 6.4 of C90, the sizeof operator is part of a constant
    >> expression.

    >
    > The preprocessor can't read keywords.
    >
    >
    > ISO/IEC 9899: 1990
    > 6.8.1 Conditional inclusion
    > Constraints
    >
    > identifiers (including those lexically identical to keywords)
    > are interpreted as described below;83
    >
    > 83 Because the controlling constant expression
    > is evaluated during translation phase 4,
    > all identifiers either are or are not macro names
    > -- there simply are no keywords, enumeration constants, etc.


    That quotation is from the C99 standard, not the C90 standard.

    In both C90 and C99, handling of identifiers in a #if directive is
    described as (C90 6.8.1, C99 6.10.1p3):

    After all replacements due to macro expansion and the defined
    unary operator have been performed, all remaining identifiers are
    replaced with the pp-number 0, and then each preprocessing token
    is converted into a token.

    Technical Corrigendum 3 (incorporated into n1256) changes this to:

    After all replacements due to macro expansion and the defined
    unary operator have been performed, all remaining identifiers

    (including those lexically identical to keywords)

    are replaced with the pp-number 0, and then each preprocessing
    token is converted into a token.

    I've marked the added text by putting it on a separate line.

    This is a clarification, not a change, since keywords are lexically
    identifiers. See DR #305,
    <http://www.open-std.org/jtc1/sc22/wg14/www/docs/dr_305.htm>.
    (It would be nice if the TC documents referred back to the DRs.)

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    Looking for software development work in the San Diego area.
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
     
    Keith Thompson, Dec 10, 2007
    #8
  9. kerravon

    pete Guest

    Keith Thompson wrote:
    >
    > pete <> writes:


    > > ISO/IEC 9899: 1990
    > > 6.8.1 Conditional inclusion
    > > Constraints
    > >
    > > identifiers (including those lexically identical to keywords)
    > > are interpreted as described below;83
    > >
    > > 83 Because the controlling constant expression
    > > is evaluated during translation phase 4,
    > > all identifiers either are or are not macro names
    > > -- there simply are no keywords, enumeration constants, etc.

    >
    > That quotation is from the C99 standard, not the C90 standard.


    That quotation is from the C90 standard.
    I think you must be using a public draft instead.


    This quotation is from the C99 standard:

    ISO/IEC 9899:1999(E)
    6.10.1 Conditional inclusion
    Constraints

    identifiers (including those lexically identical to keywords)
    are interpreted as described below;140)

    140) Because the controlling constant expression
    is evaluated during translation phase 4,
    all identifiers either are or are not macro names
    — there simply are no keywords, enumeration constants, etc.

    --
    pete
     
    pete, Dec 10, 2007
    #9
  10. pete <> writes:
    > Keith Thompson wrote:
    >> pete <> writes:
    >> > ISO/IEC 9899: 1990
    >> > 6.8.1 Conditional inclusion
    >> > Constraints
    >> >
    >> > identifiers (including those lexically identical to keywords)
    >> > are interpreted as described below;83
    >> >
    >> > 83 Because the controlling constant expression
    >> > is evaluated during translation phase 4,
    >> > all identifiers either are or are not macro names
    >> > -- there simply are no keywords, enumeration constants, etc.

    >>
    >> That quotation is from the C99 standard, not the C90 standard.

    >
    > That quotation is from the C90 standard.
    > I think you must be using a public draft instead.


    No, I'm using a copy of the actual C90 standard, but you're right, the
    quotation is from the C90 standard. I don't know how I missed that.
    Apologies.

    [...]

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    Looking for software development work in the San Diego area.
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
     
    Keith Thompson, Dec 11, 2007
    #10
  11. pete <> writes:
    > Keith Thompson wrote:
    >>
    >> pete <> writes:

    >
    >> > ISO/IEC 9899: 1990
    >> > 6.8.1 Conditional inclusion
    >> > Constraints
    >> >
    >> > identifiers (including those lexically identical to keywords)
    >> > are interpreted as described below;83
    >> >
    >> > 83 Because the controlling constant expression
    >> > is evaluated during translation phase 4,
    >> > all identifiers either are or are not macro names
    >> > -- there simply are no keywords, enumeration constants, etc.

    >>
    >> That quotation is from the C99 standard, not the C90 standard.

    >
    > That quotation is from the C90 standard.
    > I think you must be using a public draft instead.


    No, I'm using a copy of the actual C90 standard, but you're right, the
    quotation is from the C90 standard. I don't know how I missed that.
    Apologies.

    [...]

    --
    Keith Thompson (The_Other_Keith) <>
    Looking for software development work in the San Diego area.
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
     
    Keith Thompson, Dec 11, 2007
    #11
  12. kerravon

    SM Ryan Guest

    kerravon <> wrote:
    # According to 6.8 of C90, #if takes a constant expression.
    #
    # According to 6.4 of C90, the sizeof operator is part of a constant
    # expression.

    You conceptual have the stages
    (1) preprocessor
    (2) parser
    (3) code generator

    sizeof is a constant in third stage (code generator) which
    comes after the preprocessor. You should not expect this kind
    of backwards information flow from code generator to the
    preprocessor.

    One work around is write a small program that does the sizeof
    and then writes an include file with appropriate defines.

    # #if sizeof(int) >= 4
    # #define XXX "big"
    # #else
    # #define XXX "small"
    # #endif

    For example, with make you can have something like

    defineXXX.c :
    #include <stdio.h>
    int main(int N,char **P) {
    if (sizeof(int)>=4)) puts("#define XXX \"big\"");
    else puts("#define XXX \"small\"");
    return 0;
    }

    main.c:
    #include <stdio.h>
    #include "XXX.h"

    int main(void)
    {
    printf("hello %s\n", XXX);
    return (0);
    }

    makefile:
    main: main.c XXX.h
    cc -o main main.c
    XXX.h: defineXXX
    defineXXX > XXX.h
    defineXXX: defineXXX.c
    cc -o defineXXX defineXXX.c

    --
    SM Ryan http://www.rawbw.com/~wyrmwif/
    This is one wacky game show.
     
    SM Ryan, Dec 11, 2007
    #12
  13. SM Ryan <> writes:
    > kerravon <> wrote:
    > > According to 6.8 of C90, #if takes a constant expression.
    > >
    > > According to 6.4 of C90, the sizeof operator is part of a constant
    > > expression.

    >
    > You conceptual have the stages
    > (1) preprocessor
    > (2) parser
    > (3) code generator
    >
    > sizeof is a constant in third stage (code generator) which
    > comes after the preprocessor. You should not expect this kind
    > of backwards information flow from code generator to the
    > preprocessor.
    >
    > One work around is write a small program that does the sizeof
    > and then writes an include file with appropriate defines.
    >
    > > #if sizeof(int) >= 4
    > > #define XXX "big"
    > > #else
    > > #define XXX "small"
    > > #endif

    >
    > For example, with make you can have something like
    >
    > defineXXX.c :
    > #include <stdio.h>
    > int main(int N,char **P) {
    > if (sizeof(int)>=4)) puts("#define XXX \"big\"");
    > else puts("#define XXX \"small\"");
    > return 0;
    > }
    >
    > main.c:
    > #include <stdio.h>
    > #include "XXX.h"
    >
    > int main(void)
    > {
    > printf("hello %s\n", XXX);
    > return (0);
    > }
    >
    > makefile:
    > main: main.c XXX.h
    > cc -o main main.c
    > XXX.h: defineXXX
    > defineXXX > XXX.h
    > defineXXX: defineXXX.c
    > cc -o defineXXX defineXXX.c


    Taking the system-specific makefile syntax as an *example* of the
    general approach, I'll point out that this works only when the
    software is being compiled on the same system that it's being compiled
    for. For cross-compilation, you'd need to arrange for the "defineXXX"
    program to be executed on the target, and the output copied back to
    the host system.

    <OT>And you'd want "./defineXXX", not "defineXXX".</OT>

    --
    Keith Thompson (The_Other_Keith) <>
    Looking for software development work in the San Diego area.
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
     
    Keith Thompson, Dec 11, 2007
    #13
    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.

Share This Page