To which degree does the C-preprocessor regard integer literal suffixes?Standards for the C and/or C++ preprocessors?Which is better option to use for dividing an integer number by 2?printf() in 32bit g++ and 64bit g++ deals arguments differently?Why does the C preprocessor interpret the word “linux” as the constant “1”?Interpret java strings containing integer literals (dec, hex & oct notation) as integer valuesWhat happens exactly when a 32bit integer overflows on a 64bit machine?Promotion when evaluating constant integer expressions in preprocessor directives - GCCWhat does the integer suffix J mean?Are the L and LL integer suffixes ever needed?Defending “U” suffix after Hex literalsWhy does gcc converts floating point literals to double even after using an f suffix but clang seems not?

Testing using real data of the customer

Why is the Eisenstein ideal paper so great?

Is keeping the forking link on a true fork necessary (Github/GPL)?

What were the Ethiopians doing in Xerxes' army?

Heat lost in ideal capacitor charging

I want to ask company flying me out for office tour if I can bring my fiance

Do copyright notices need to be placed at the beginning of a file?

Is it legal to have an abortion in another state or abroad?

On San Andreas Speedruns, why do players blow up the Picador in the mission Ryder?

Why is 'additive' EQ more difficult to use than 'subtractive'?

Can a ring of spell storing and access to Find spells produce an endless menagerie?

Why A=2 and B=1 in the call signs for Spirit and Opportunity?

What is the recommended procedure to land a taildragger in a crosswind?

Of strange atmospheres - the survivable but unbreathable

...And they were stumped for a long time

Who knighted this character?

Underwater city sanitation

Why does the Starter Set wizard have six spells in their spellbook?

How was Daenerys able to legitimise Gendry?

Did this character show any indication of wanting to rule before S8E6?

Why was this character made Grand Maester?

Why did other houses not demand this?

First Program Tic-Tac-Toe

What did the 'turbo' button actually do?



To which degree does the C-preprocessor regard integer literal suffixes?


Standards for the C and/or C++ preprocessors?Which is better option to use for dividing an integer number by 2?printf() in 32bit g++ and 64bit g++ deals arguments differently?Why does the C preprocessor interpret the word “linux” as the constant “1”?Interpret java strings containing integer literals (dec, hex & oct notation) as integer valuesWhat happens exactly when a 32bit integer overflows on a 64bit machine?Promotion when evaluating constant integer expressions in preprocessor directives - GCCWhat does the integer suffix J mean?Are the L and LL integer suffixes ever needed?Defending “U” suffix after Hex literalsWhy does gcc converts floating point literals to double even after using an f suffix but clang seems not?






.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty height:90px;width:728px;box-sizing:border-box;








7















Today, I stumbled over something like this:



#define FOO 2u

#if (FOO == 2)
unsigned int foo = FOO;
#endif


Regardless of why the code is as it is (let's not question the why), I was wondering to which degree the preprocessor can even handle integer literal suffixes. I was actually surprised that it works at all.
After doing some experiments with gcc and C99 with this code ...



#include <stdio.h>

int main()

#if (1u == 1)
printf("1u == 1n");
#endif

#if (1u + 1l == 2ll)
printf("1u + 1l == 2lln");
#endif

#if (1ull - 2u == -1)
printf("1ull - 2u == -1n");
#endif

#if (1u - 2u == 0xFFFFFFFFFFFFFFFF)
printf("1u - 2u == 0xFFFFFFFFFFFFFFFFn");
#endif

#if (-1 == 0xFFFFFFFFFFFFFFFF)
printf("-1 == 0xFFFFFFFFFFFFFFFFn");
#endif

#if (-1l == 0xFFFFFFFFFFFFFFFF)
printf("-1l == 0xFFFFFFFFFFFFFFFFn");
#endif

#if (-1ll == 0xFFFFFFFFFFFFFFFF)
printf("-1ll == 0xFFFFFFFFFFFFFFFFn");
#endif



... which just prints all the statements:



1u == 1
1u + 1l == 2ll
1ull - 2u == -1
1u - 2u == 0xFFFFFFFFFFFFFFFF
-1 == 0xFFFFFFFFFFFFFFFF
-1l == 0xFFFFFFFFFFFFFFFF
-1ll == 0xFFFFFFFFFFFFFFFF


... I guess the preprocessor simply ignores integer literal suffixes alltogether and probably always does arithmetics and comparisons in the native integer size, in this case 64 bit?



So, here is the stuff I'd like to know:



  1. To which degree does the Preprocessor regard integer literal suffixes? Or does it just ignore them?

  2. Are there any dependencies or different behaviors with different environments, e.g. different compilers, C vs. C++, 32bit vs. 64bit machine etc.? I.e., what does the Preprocessor's behavior depend on?

  3. Where is all that specified/documented?

I wanted to find out by myself and checked out
wikipedia and the C standard
(working paper). I found
information about integer suffixes and information about the preprocessor but
none about the combination of these. Obviously, I have also googled it but didn't get any useful results.



I have seen this stackoverflow thread that clarifies where it should be specified, but yet, I couldn't find an answer for my questions.










share|improve this question

















  • 8





    C11 §6.10.1 Conditional inclusion ¶4: … For the purposes of this token conversion and evaluation, all signed integer types and all unsigned integer types act as if they have the same representation as, respectively, the types intmax_t and uintmax_t defined in the header <stdint.h>.

    – Jonathan Leffler
    5 hours ago


















7















Today, I stumbled over something like this:



#define FOO 2u

#if (FOO == 2)
unsigned int foo = FOO;
#endif


Regardless of why the code is as it is (let's not question the why), I was wondering to which degree the preprocessor can even handle integer literal suffixes. I was actually surprised that it works at all.
After doing some experiments with gcc and C99 with this code ...



#include <stdio.h>

int main()

#if (1u == 1)
printf("1u == 1n");
#endif

#if (1u + 1l == 2ll)
printf("1u + 1l == 2lln");
#endif

#if (1ull - 2u == -1)
printf("1ull - 2u == -1n");
#endif

#if (1u - 2u == 0xFFFFFFFFFFFFFFFF)
printf("1u - 2u == 0xFFFFFFFFFFFFFFFFn");
#endif

#if (-1 == 0xFFFFFFFFFFFFFFFF)
printf("-1 == 0xFFFFFFFFFFFFFFFFn");
#endif

#if (-1l == 0xFFFFFFFFFFFFFFFF)
printf("-1l == 0xFFFFFFFFFFFFFFFFn");
#endif

#if (-1ll == 0xFFFFFFFFFFFFFFFF)
printf("-1ll == 0xFFFFFFFFFFFFFFFFn");
#endif



... which just prints all the statements:



1u == 1
1u + 1l == 2ll
1ull - 2u == -1
1u - 2u == 0xFFFFFFFFFFFFFFFF
-1 == 0xFFFFFFFFFFFFFFFF
-1l == 0xFFFFFFFFFFFFFFFF
-1ll == 0xFFFFFFFFFFFFFFFF


... I guess the preprocessor simply ignores integer literal suffixes alltogether and probably always does arithmetics and comparisons in the native integer size, in this case 64 bit?



So, here is the stuff I'd like to know:



  1. To which degree does the Preprocessor regard integer literal suffixes? Or does it just ignore them?

  2. Are there any dependencies or different behaviors with different environments, e.g. different compilers, C vs. C++, 32bit vs. 64bit machine etc.? I.e., what does the Preprocessor's behavior depend on?

  3. Where is all that specified/documented?

I wanted to find out by myself and checked out
wikipedia and the C standard
(working paper). I found
information about integer suffixes and information about the preprocessor but
none about the combination of these. Obviously, I have also googled it but didn't get any useful results.



I have seen this stackoverflow thread that clarifies where it should be specified, but yet, I couldn't find an answer for my questions.










share|improve this question

















  • 8





    C11 §6.10.1 Conditional inclusion ¶4: … For the purposes of this token conversion and evaluation, all signed integer types and all unsigned integer types act as if they have the same representation as, respectively, the types intmax_t and uintmax_t defined in the header <stdint.h>.

    – Jonathan Leffler
    5 hours ago














7












7








7








Today, I stumbled over something like this:



#define FOO 2u

#if (FOO == 2)
unsigned int foo = FOO;
#endif


Regardless of why the code is as it is (let's not question the why), I was wondering to which degree the preprocessor can even handle integer literal suffixes. I was actually surprised that it works at all.
After doing some experiments with gcc and C99 with this code ...



#include <stdio.h>

int main()

#if (1u == 1)
printf("1u == 1n");
#endif

#if (1u + 1l == 2ll)
printf("1u + 1l == 2lln");
#endif

#if (1ull - 2u == -1)
printf("1ull - 2u == -1n");
#endif

#if (1u - 2u == 0xFFFFFFFFFFFFFFFF)
printf("1u - 2u == 0xFFFFFFFFFFFFFFFFn");
#endif

#if (-1 == 0xFFFFFFFFFFFFFFFF)
printf("-1 == 0xFFFFFFFFFFFFFFFFn");
#endif

#if (-1l == 0xFFFFFFFFFFFFFFFF)
printf("-1l == 0xFFFFFFFFFFFFFFFFn");
#endif

#if (-1ll == 0xFFFFFFFFFFFFFFFF)
printf("-1ll == 0xFFFFFFFFFFFFFFFFn");
#endif



... which just prints all the statements:



1u == 1
1u + 1l == 2ll
1ull - 2u == -1
1u - 2u == 0xFFFFFFFFFFFFFFFF
-1 == 0xFFFFFFFFFFFFFFFF
-1l == 0xFFFFFFFFFFFFFFFF
-1ll == 0xFFFFFFFFFFFFFFFF


... I guess the preprocessor simply ignores integer literal suffixes alltogether and probably always does arithmetics and comparisons in the native integer size, in this case 64 bit?



So, here is the stuff I'd like to know:



  1. To which degree does the Preprocessor regard integer literal suffixes? Or does it just ignore them?

  2. Are there any dependencies or different behaviors with different environments, e.g. different compilers, C vs. C++, 32bit vs. 64bit machine etc.? I.e., what does the Preprocessor's behavior depend on?

  3. Where is all that specified/documented?

I wanted to find out by myself and checked out
wikipedia and the C standard
(working paper). I found
information about integer suffixes and information about the preprocessor but
none about the combination of these. Obviously, I have also googled it but didn't get any useful results.



I have seen this stackoverflow thread that clarifies where it should be specified, but yet, I couldn't find an answer for my questions.










share|improve this question














Today, I stumbled over something like this:



#define FOO 2u

#if (FOO == 2)
unsigned int foo = FOO;
#endif


Regardless of why the code is as it is (let's not question the why), I was wondering to which degree the preprocessor can even handle integer literal suffixes. I was actually surprised that it works at all.
After doing some experiments with gcc and C99 with this code ...



#include <stdio.h>

int main()

#if (1u == 1)
printf("1u == 1n");
#endif

#if (1u + 1l == 2ll)
printf("1u + 1l == 2lln");
#endif

#if (1ull - 2u == -1)
printf("1ull - 2u == -1n");
#endif

#if (1u - 2u == 0xFFFFFFFFFFFFFFFF)
printf("1u - 2u == 0xFFFFFFFFFFFFFFFFn");
#endif

#if (-1 == 0xFFFFFFFFFFFFFFFF)
printf("-1 == 0xFFFFFFFFFFFFFFFFn");
#endif

#if (-1l == 0xFFFFFFFFFFFFFFFF)
printf("-1l == 0xFFFFFFFFFFFFFFFFn");
#endif

#if (-1ll == 0xFFFFFFFFFFFFFFFF)
printf("-1ll == 0xFFFFFFFFFFFFFFFFn");
#endif



... which just prints all the statements:



1u == 1
1u + 1l == 2ll
1ull - 2u == -1
1u - 2u == 0xFFFFFFFFFFFFFFFF
-1 == 0xFFFFFFFFFFFFFFFF
-1l == 0xFFFFFFFFFFFFFFFF
-1ll == 0xFFFFFFFFFFFFFFFF


... I guess the preprocessor simply ignores integer literal suffixes alltogether and probably always does arithmetics and comparisons in the native integer size, in this case 64 bit?



So, here is the stuff I'd like to know:



  1. To which degree does the Preprocessor regard integer literal suffixes? Or does it just ignore them?

  2. Are there any dependencies or different behaviors with different environments, e.g. different compilers, C vs. C++, 32bit vs. 64bit machine etc.? I.e., what does the Preprocessor's behavior depend on?

  3. Where is all that specified/documented?

I wanted to find out by myself and checked out
wikipedia and the C standard
(working paper). I found
information about integer suffixes and information about the preprocessor but
none about the combination of these. Obviously, I have also googled it but didn't get any useful results.



I have seen this stackoverflow thread that clarifies where it should be specified, but yet, I couldn't find an answer for my questions.







c++ c integer c-preprocessor suffix






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked 5 hours ago









MichiMichi

414317




414317







  • 8





    C11 §6.10.1 Conditional inclusion ¶4: … For the purposes of this token conversion and evaluation, all signed integer types and all unsigned integer types act as if they have the same representation as, respectively, the types intmax_t and uintmax_t defined in the header <stdint.h>.

    – Jonathan Leffler
    5 hours ago













  • 8





    C11 §6.10.1 Conditional inclusion ¶4: … For the purposes of this token conversion and evaluation, all signed integer types and all unsigned integer types act as if they have the same representation as, respectively, the types intmax_t and uintmax_t defined in the header <stdint.h>.

    – Jonathan Leffler
    5 hours ago








8




8





C11 §6.10.1 Conditional inclusion ¶4: … For the purposes of this token conversion and evaluation, all signed integer types and all unsigned integer types act as if they have the same representation as, respectively, the types intmax_t and uintmax_t defined in the header <stdint.h>.

– Jonathan Leffler
5 hours ago






C11 §6.10.1 Conditional inclusion ¶4: … For the purposes of this token conversion and evaluation, all signed integer types and all unsigned integer types act as if they have the same representation as, respectively, the types intmax_t and uintmax_t defined in the header <stdint.h>.

– Jonathan Leffler
5 hours ago













4 Answers
4






active

oldest

votes


















2















  1. To which degree does the Preprocessor regard integer literal suffixes? Or does it just ignore them?



The type suffixes of integer constants are not inherently meaningful to the preprocessor, but they are an inherent part of the corresponding preprocessing tokens, not separate. The standard has this to say about them:




A preprocessing number begins with a digit optionally preceded by a
period (.) and may be followed by valid identifier characters and the
character sequences e+, e-, E+, E-, p+, p-, P+, or P-.



Preprocessing number tokens lexically include all floating and
integer constant tokens.




(C11 6.4.8/2-3; emphasis added)



For the most part, the preprocessor doesn't treat preprocessing tokens of this type any differently than any other. The exception is in the controlling expressions of #if directives, which are evaluated by performing macro expansion, replacing identifiers with 0, and then converting each preprocessing token into a token before evaluating the result according to C rules. Converting to tokens accounts for the type suffixes, yielding bona fide integer constants.



This does not necessarily produce results identical to those you would get from runtime evaluation of the same expressions, however, because




For the purposes of this token conversion and evaluation, all signed
integer types and all unsigned integer types act as if they have the
same representation as, respectively, the types intmax_t and uintmax_t.




(C2011, 6.10.1/4)



You go on to ask




  1. Are there any dependencies or different behaviors with different environments, e.g. different compilers, C vs. C++, 32bit vs. 64bit machine etc.? I.e., what does the Preprocessor's behavior depend on?



The only direct dependency is the implementation's definitions of intmax_t and uintmax_t. These are not directly tied to language choice or machine architecture, though there may be correlations with those.




  1. Where is all that specified/documented?



In the respective languages' language specifications, of course. I've cited the two of the more relevant sections of the C11 specification, and linked you to a late draft of that standard. (The current C is C18, but it hasn't changed in any of these regards.)






share|improve this answer


















  • 1





    The suffixes of integer constants are meaningful to the preprocessor because they affect signedness. -1u < 0 evaluates to false, but -1l < 0 evaluates to true.

    – Eric Postpischil
    5 hours ago











  • Yes, @EricPostpischil, they affect evaluation of the control expressions of #if directives. I'm perhaps splitting hairs too finely here, but although that's meaningful to C, I do not consider it meaningful to the preprocessor.

    – John Bollinger
    5 hours ago











  • they affect evaluation of the control expressions of #if and I do not consider it meaningful to the preprocessor seem incongruous.

    – ryyker
    4 hours ago











  • Clearly the meanings of -1u < 0 and -1l < 0 in a #if statement are different, since they evaluate to different results, and the selection of which statements to include thus differs. And the only difference is the suffix. Therefore, the suffix is meaningful to preprocessing.

    – Eric Postpischil
    4 hours ago






  • 1





    As I said, I am splitting hairs rather finely. In particular, I am placing the evaluation of the expression outside the scope of the preprocessor proper, on account of (1) it operating on tokens, not preprocessing tokens, and (2) it being governed by the regular C rules for evaluation, as opposed to special rules pertaining to the preprocessor. This is appropos to the question, which expresses surprise about the C syntax for integer constants being recognized and handled. Yes it is, because no other is defined for the purpose.

    – John Bollinger
    4 hours ago



















4














As I noted in a comment, this is defined in the C standard. Here's the complete text of §6.10.1 ¶4 (and the two footnotes):




C11 §6.10.1 Conditional inclusion



¶4 Prior to evaluation, macro invocations in the list of preprocessing tokens that will become the controlling constant expression are replaced (except for those macro names modified by the defined unary operator), just as in normal text. If the token defined is generated as a result of this replacement process or use of the defined unary operator does not match one of the two specified forms prior to macro replacement, the behavior is undefined. 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. The resulting tokens compose the controlling constant expression which is evaluated according to the rules of 6.6. For the purposes of this token conversion and evaluation, all signed integer types and all unsigned integer types act as if they have the same representation as, respectively, the types intmax_t and uintmax_t defined in the header <stdint.h>.167) This includes interpreting character constants, which may involve converting escape sequences into execution character set members. Whether the numeric value for these character constants matches the value obtained when an identical character constant occurs in an expression (other than within a #if or #elif directive) is implementation-defined.168) Also, whether a single-character character constant may have a negative value is implementation-defined.



167 167) Thus, on an implementation where INT_MAX is 0x7FFF and UINT_MAX is 0xFFFF, the constant 0x8000 is signed and positive within a #if expression even though it would be unsigned in translation phase 7.



168 Thus, the constant expression in the following #if directive and if statement is not guaranteed to evaluate to the same value in these two contexts.



#if 'z' - 'a' == 25
if ('z' - 'a' == 25)



Section 6.6 is §6.6 Constant expressions, which details the differences between the full expressions in section §6.5 Expressions and constant expressions.



In effect, the preprocessor largely ignores the suffixes. Hexadecimal constants are unsigned. The results you show are to be expected on a machine where intmax_t and uintmax_t are 64-bit quantities. If the limits on the intmax_t and uintmax_t were larger, some of the expressions might change.






share|improve this answer




















  • 1





    The preprocessor cannot ignore the suffixes. It might ignore their width effects, but not the signedness.

    – Eric Postpischil
    5 hours ago


















3














C 2018 6.10.1 deals with conditional inclusion (#if and related statements and the defined operator). Paragraph 1 says:




The expression that controls conditional inclusion shall be an integer constant expression except that: identifiers (including those lexically identical to keywords) are interpreted as described below; and it may contain unary operator expressions of the form



defined identifier



or



defined ( identifier )




Integer constant expression is defined in 6.6 6:




An integer constant expression shall have integer type and shall only have operands that are integer constants, enumeration constants, character constants, sizeof expressions whose results are integer constants, _Alignof expressions, and floating constants that are the immediate operands of casts. Cast operators in an integer constant expression shall only convert arithmetic types to integer types, except as part of an operand to the sizeof or _Alignof operator.




That paragraph is for C generally, not just the preprocessor. So the expressions that can appear in #if statements are the same as the integer constant expressions that can appear generally in C. However, as stated in the quote above, sizeof and _Alignof are just identifiers; they are not recognized as C operators. In particular, 6.10.1 4 tells us:




… 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,…




So, where sizeof or _Alignof appear in a #if expression, it becomes 0. Thus, a #if expression can only have operands that are constants and defined expressions.



Paragraph 4 goes on to say:




… The resulting tokens compose the controlling constant expression which is evaluated according to the rules of 6.6. For the purposes of this token conversion and evaluation, all signed integer types and all unsigned integer types act as if they have the same representation as, respectively, the types intmax_t and uintmax_t defined in the header <stdint.h>.…




6.6 is the section for constant expressions.



So, the compiler will accept integer suffixes in #if expressions, and that does not depend on the C implementation (for the suffixes required in the core C language; implementations could allow extensions). However, all the arithmetic will be performed using intmax_t or uintmax_t, and those do depend on the implementation. If your expressions do not depend on the width of integers above the minimum required1, they should be evaluated the same in any C implementation.



Additionally, paragraph 4 goes on to say there may be some variations with character constants and values, which I omit here as it is not relevant to this question.



Footnote



1intmax_t designates a signed type capable of representing any value of any signed integer type (7.20.1.5 1), and long long int is a signed type that must be at least 64 bits (5.2.4.2.1 1), so any conforming C implementation must provide 64-bit integer arithmetic in the preprocessor.






share|improve this answer

























  • About So the expressions that can appear in #if statements are the same as the integer constant expressions that can appear generally in C.: I guess not quite. A footnote in chapter "Constant expressions" reads Further constraints that apply to the integer constant expressions used in conditional-inclusion preprocessing directives are discussed in 6.10.1. and then in a footnote of 6.10.1: 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.

    – Michi
    3 hours ago


















0














TLDR dumbed down version:



l and ll are effectively (not literally!) ignored by the preprocessor conditionals (basically, everything is treated as if it had a ll suffix), however u is considered (normally, as for every C integer constant)!



After reading all the marvelous answers, I created some more examples that reveal some expected but yet interesting behavior:



#include <stdio.h>

int main()

#if (1 - 2u > 0) // If one operand is unsigned, the result is unsigned.
// Usual implicit type conversion.
printf("1 - 2u > 0n");
#endif

#if (0 < 0xFFFFFFFFFFFFFFFF)
printf("0 < 0xFFFFFFFFFFFFFFFFn");
#endif

#if (-1 < 0)
printf("-1 < 0n");
#endif

#if (-1 < 0xFFFFFFFFFFFFFFFF)
printf("-1 < 0xFFFFFFFFFFFFFFFFn"); // nope
#elif (-1 > 0xFFFFFFFFFFFFFFFF)
printf("-1 > 0xFFFFFFFFFFFFFFFFn"); // nope, obviously
#endif

#if (-1 == 0xFFFFFFFFFFFFFFFF)
printf("-1 == 0xFFFFFFFFFFFFFFFF (!!!)n");
#endif



With this output:



1 - 2u > 0
0 < 0xFFFFFFFFFFFFFFFF
-1 < 0
-1 == 0xFFFFFFFFFFFFFFFF (!!!)





share|improve this answer























    Your Answer






    StackExchange.ifUsing("editor", function ()
    StackExchange.using("externalEditor", function ()
    StackExchange.using("snippets", function ()
    StackExchange.snippets.init();
    );
    );
    , "code-snippets");

    StackExchange.ready(function()
    var channelOptions =
    tags: "".split(" "),
    id: "1"
    ;
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function()
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled)
    StackExchange.using("snippets", function()
    createEditor();
    );

    else
    createEditor();

    );

    function createEditor()
    StackExchange.prepareEditor(
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader:
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    ,
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    );



    );













    draft saved

    draft discarded


















    StackExchange.ready(
    function ()
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f56244247%2fto-which-degree-does-the-c-preprocessor-regard-integer-literal-suffixes%23new-answer', 'question_page');

    );

    Post as a guest















    Required, but never shown

























    4 Answers
    4






    active

    oldest

    votes








    4 Answers
    4






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    2















    1. To which degree does the Preprocessor regard integer literal suffixes? Or does it just ignore them?



    The type suffixes of integer constants are not inherently meaningful to the preprocessor, but they are an inherent part of the corresponding preprocessing tokens, not separate. The standard has this to say about them:




    A preprocessing number begins with a digit optionally preceded by a
    period (.) and may be followed by valid identifier characters and the
    character sequences e+, e-, E+, E-, p+, p-, P+, or P-.



    Preprocessing number tokens lexically include all floating and
    integer constant tokens.




    (C11 6.4.8/2-3; emphasis added)



    For the most part, the preprocessor doesn't treat preprocessing tokens of this type any differently than any other. The exception is in the controlling expressions of #if directives, which are evaluated by performing macro expansion, replacing identifiers with 0, and then converting each preprocessing token into a token before evaluating the result according to C rules. Converting to tokens accounts for the type suffixes, yielding bona fide integer constants.



    This does not necessarily produce results identical to those you would get from runtime evaluation of the same expressions, however, because




    For the purposes of this token conversion and evaluation, all signed
    integer types and all unsigned integer types act as if they have the
    same representation as, respectively, the types intmax_t and uintmax_t.




    (C2011, 6.10.1/4)



    You go on to ask




    1. Are there any dependencies or different behaviors with different environments, e.g. different compilers, C vs. C++, 32bit vs. 64bit machine etc.? I.e., what does the Preprocessor's behavior depend on?



    The only direct dependency is the implementation's definitions of intmax_t and uintmax_t. These are not directly tied to language choice or machine architecture, though there may be correlations with those.




    1. Where is all that specified/documented?



    In the respective languages' language specifications, of course. I've cited the two of the more relevant sections of the C11 specification, and linked you to a late draft of that standard. (The current C is C18, but it hasn't changed in any of these regards.)






    share|improve this answer


















    • 1





      The suffixes of integer constants are meaningful to the preprocessor because they affect signedness. -1u < 0 evaluates to false, but -1l < 0 evaluates to true.

      – Eric Postpischil
      5 hours ago











    • Yes, @EricPostpischil, they affect evaluation of the control expressions of #if directives. I'm perhaps splitting hairs too finely here, but although that's meaningful to C, I do not consider it meaningful to the preprocessor.

      – John Bollinger
      5 hours ago











    • they affect evaluation of the control expressions of #if and I do not consider it meaningful to the preprocessor seem incongruous.

      – ryyker
      4 hours ago











    • Clearly the meanings of -1u < 0 and -1l < 0 in a #if statement are different, since they evaluate to different results, and the selection of which statements to include thus differs. And the only difference is the suffix. Therefore, the suffix is meaningful to preprocessing.

      – Eric Postpischil
      4 hours ago






    • 1





      As I said, I am splitting hairs rather finely. In particular, I am placing the evaluation of the expression outside the scope of the preprocessor proper, on account of (1) it operating on tokens, not preprocessing tokens, and (2) it being governed by the regular C rules for evaluation, as opposed to special rules pertaining to the preprocessor. This is appropos to the question, which expresses surprise about the C syntax for integer constants being recognized and handled. Yes it is, because no other is defined for the purpose.

      – John Bollinger
      4 hours ago
















    2















    1. To which degree does the Preprocessor regard integer literal suffixes? Or does it just ignore them?



    The type suffixes of integer constants are not inherently meaningful to the preprocessor, but they are an inherent part of the corresponding preprocessing tokens, not separate. The standard has this to say about them:




    A preprocessing number begins with a digit optionally preceded by a
    period (.) and may be followed by valid identifier characters and the
    character sequences e+, e-, E+, E-, p+, p-, P+, or P-.



    Preprocessing number tokens lexically include all floating and
    integer constant tokens.




    (C11 6.4.8/2-3; emphasis added)



    For the most part, the preprocessor doesn't treat preprocessing tokens of this type any differently than any other. The exception is in the controlling expressions of #if directives, which are evaluated by performing macro expansion, replacing identifiers with 0, and then converting each preprocessing token into a token before evaluating the result according to C rules. Converting to tokens accounts for the type suffixes, yielding bona fide integer constants.



    This does not necessarily produce results identical to those you would get from runtime evaluation of the same expressions, however, because




    For the purposes of this token conversion and evaluation, all signed
    integer types and all unsigned integer types act as if they have the
    same representation as, respectively, the types intmax_t and uintmax_t.




    (C2011, 6.10.1/4)



    You go on to ask




    1. Are there any dependencies or different behaviors with different environments, e.g. different compilers, C vs. C++, 32bit vs. 64bit machine etc.? I.e., what does the Preprocessor's behavior depend on?



    The only direct dependency is the implementation's definitions of intmax_t and uintmax_t. These are not directly tied to language choice or machine architecture, though there may be correlations with those.




    1. Where is all that specified/documented?



    In the respective languages' language specifications, of course. I've cited the two of the more relevant sections of the C11 specification, and linked you to a late draft of that standard. (The current C is C18, but it hasn't changed in any of these regards.)






    share|improve this answer


















    • 1





      The suffixes of integer constants are meaningful to the preprocessor because they affect signedness. -1u < 0 evaluates to false, but -1l < 0 evaluates to true.

      – Eric Postpischil
      5 hours ago











    • Yes, @EricPostpischil, they affect evaluation of the control expressions of #if directives. I'm perhaps splitting hairs too finely here, but although that's meaningful to C, I do not consider it meaningful to the preprocessor.

      – John Bollinger
      5 hours ago











    • they affect evaluation of the control expressions of #if and I do not consider it meaningful to the preprocessor seem incongruous.

      – ryyker
      4 hours ago











    • Clearly the meanings of -1u < 0 and -1l < 0 in a #if statement are different, since they evaluate to different results, and the selection of which statements to include thus differs. And the only difference is the suffix. Therefore, the suffix is meaningful to preprocessing.

      – Eric Postpischil
      4 hours ago






    • 1





      As I said, I am splitting hairs rather finely. In particular, I am placing the evaluation of the expression outside the scope of the preprocessor proper, on account of (1) it operating on tokens, not preprocessing tokens, and (2) it being governed by the regular C rules for evaluation, as opposed to special rules pertaining to the preprocessor. This is appropos to the question, which expresses surprise about the C syntax for integer constants being recognized and handled. Yes it is, because no other is defined for the purpose.

      – John Bollinger
      4 hours ago














    2












    2








    2








    1. To which degree does the Preprocessor regard integer literal suffixes? Or does it just ignore them?



    The type suffixes of integer constants are not inherently meaningful to the preprocessor, but they are an inherent part of the corresponding preprocessing tokens, not separate. The standard has this to say about them:




    A preprocessing number begins with a digit optionally preceded by a
    period (.) and may be followed by valid identifier characters and the
    character sequences e+, e-, E+, E-, p+, p-, P+, or P-.



    Preprocessing number tokens lexically include all floating and
    integer constant tokens.




    (C11 6.4.8/2-3; emphasis added)



    For the most part, the preprocessor doesn't treat preprocessing tokens of this type any differently than any other. The exception is in the controlling expressions of #if directives, which are evaluated by performing macro expansion, replacing identifiers with 0, and then converting each preprocessing token into a token before evaluating the result according to C rules. Converting to tokens accounts for the type suffixes, yielding bona fide integer constants.



    This does not necessarily produce results identical to those you would get from runtime evaluation of the same expressions, however, because




    For the purposes of this token conversion and evaluation, all signed
    integer types and all unsigned integer types act as if they have the
    same representation as, respectively, the types intmax_t and uintmax_t.




    (C2011, 6.10.1/4)



    You go on to ask




    1. Are there any dependencies or different behaviors with different environments, e.g. different compilers, C vs. C++, 32bit vs. 64bit machine etc.? I.e., what does the Preprocessor's behavior depend on?



    The only direct dependency is the implementation's definitions of intmax_t and uintmax_t. These are not directly tied to language choice or machine architecture, though there may be correlations with those.




    1. Where is all that specified/documented?



    In the respective languages' language specifications, of course. I've cited the two of the more relevant sections of the C11 specification, and linked you to a late draft of that standard. (The current C is C18, but it hasn't changed in any of these regards.)






    share|improve this answer














    1. To which degree does the Preprocessor regard integer literal suffixes? Or does it just ignore them?



    The type suffixes of integer constants are not inherently meaningful to the preprocessor, but they are an inherent part of the corresponding preprocessing tokens, not separate. The standard has this to say about them:




    A preprocessing number begins with a digit optionally preceded by a
    period (.) and may be followed by valid identifier characters and the
    character sequences e+, e-, E+, E-, p+, p-, P+, or P-.



    Preprocessing number tokens lexically include all floating and
    integer constant tokens.




    (C11 6.4.8/2-3; emphasis added)



    For the most part, the preprocessor doesn't treat preprocessing tokens of this type any differently than any other. The exception is in the controlling expressions of #if directives, which are evaluated by performing macro expansion, replacing identifiers with 0, and then converting each preprocessing token into a token before evaluating the result according to C rules. Converting to tokens accounts for the type suffixes, yielding bona fide integer constants.



    This does not necessarily produce results identical to those you would get from runtime evaluation of the same expressions, however, because




    For the purposes of this token conversion and evaluation, all signed
    integer types and all unsigned integer types act as if they have the
    same representation as, respectively, the types intmax_t and uintmax_t.




    (C2011, 6.10.1/4)



    You go on to ask




    1. Are there any dependencies or different behaviors with different environments, e.g. different compilers, C vs. C++, 32bit vs. 64bit machine etc.? I.e., what does the Preprocessor's behavior depend on?



    The only direct dependency is the implementation's definitions of intmax_t and uintmax_t. These are not directly tied to language choice or machine architecture, though there may be correlations with those.




    1. Where is all that specified/documented?



    In the respective languages' language specifications, of course. I've cited the two of the more relevant sections of the C11 specification, and linked you to a late draft of that standard. (The current C is C18, but it hasn't changed in any of these regards.)







    share|improve this answer












    share|improve this answer



    share|improve this answer










    answered 5 hours ago









    John BollingerJohn Bollinger

    89k84684




    89k84684







    • 1





      The suffixes of integer constants are meaningful to the preprocessor because they affect signedness. -1u < 0 evaluates to false, but -1l < 0 evaluates to true.

      – Eric Postpischil
      5 hours ago











    • Yes, @EricPostpischil, they affect evaluation of the control expressions of #if directives. I'm perhaps splitting hairs too finely here, but although that's meaningful to C, I do not consider it meaningful to the preprocessor.

      – John Bollinger
      5 hours ago











    • they affect evaluation of the control expressions of #if and I do not consider it meaningful to the preprocessor seem incongruous.

      – ryyker
      4 hours ago











    • Clearly the meanings of -1u < 0 and -1l < 0 in a #if statement are different, since they evaluate to different results, and the selection of which statements to include thus differs. And the only difference is the suffix. Therefore, the suffix is meaningful to preprocessing.

      – Eric Postpischil
      4 hours ago






    • 1





      As I said, I am splitting hairs rather finely. In particular, I am placing the evaluation of the expression outside the scope of the preprocessor proper, on account of (1) it operating on tokens, not preprocessing tokens, and (2) it being governed by the regular C rules for evaluation, as opposed to special rules pertaining to the preprocessor. This is appropos to the question, which expresses surprise about the C syntax for integer constants being recognized and handled. Yes it is, because no other is defined for the purpose.

      – John Bollinger
      4 hours ago













    • 1





      The suffixes of integer constants are meaningful to the preprocessor because they affect signedness. -1u < 0 evaluates to false, but -1l < 0 evaluates to true.

      – Eric Postpischil
      5 hours ago











    • Yes, @EricPostpischil, they affect evaluation of the control expressions of #if directives. I'm perhaps splitting hairs too finely here, but although that's meaningful to C, I do not consider it meaningful to the preprocessor.

      – John Bollinger
      5 hours ago











    • they affect evaluation of the control expressions of #if and I do not consider it meaningful to the preprocessor seem incongruous.

      – ryyker
      4 hours ago











    • Clearly the meanings of -1u < 0 and -1l < 0 in a #if statement are different, since they evaluate to different results, and the selection of which statements to include thus differs. And the only difference is the suffix. Therefore, the suffix is meaningful to preprocessing.

      – Eric Postpischil
      4 hours ago






    • 1





      As I said, I am splitting hairs rather finely. In particular, I am placing the evaluation of the expression outside the scope of the preprocessor proper, on account of (1) it operating on tokens, not preprocessing tokens, and (2) it being governed by the regular C rules for evaluation, as opposed to special rules pertaining to the preprocessor. This is appropos to the question, which expresses surprise about the C syntax for integer constants being recognized and handled. Yes it is, because no other is defined for the purpose.

      – John Bollinger
      4 hours ago








    1




    1





    The suffixes of integer constants are meaningful to the preprocessor because they affect signedness. -1u < 0 evaluates to false, but -1l < 0 evaluates to true.

    – Eric Postpischil
    5 hours ago





    The suffixes of integer constants are meaningful to the preprocessor because they affect signedness. -1u < 0 evaluates to false, but -1l < 0 evaluates to true.

    – Eric Postpischil
    5 hours ago













    Yes, @EricPostpischil, they affect evaluation of the control expressions of #if directives. I'm perhaps splitting hairs too finely here, but although that's meaningful to C, I do not consider it meaningful to the preprocessor.

    – John Bollinger
    5 hours ago





    Yes, @EricPostpischil, they affect evaluation of the control expressions of #if directives. I'm perhaps splitting hairs too finely here, but although that's meaningful to C, I do not consider it meaningful to the preprocessor.

    – John Bollinger
    5 hours ago













    they affect evaluation of the control expressions of #if and I do not consider it meaningful to the preprocessor seem incongruous.

    – ryyker
    4 hours ago





    they affect evaluation of the control expressions of #if and I do not consider it meaningful to the preprocessor seem incongruous.

    – ryyker
    4 hours ago













    Clearly the meanings of -1u < 0 and -1l < 0 in a #if statement are different, since they evaluate to different results, and the selection of which statements to include thus differs. And the only difference is the suffix. Therefore, the suffix is meaningful to preprocessing.

    – Eric Postpischil
    4 hours ago





    Clearly the meanings of -1u < 0 and -1l < 0 in a #if statement are different, since they evaluate to different results, and the selection of which statements to include thus differs. And the only difference is the suffix. Therefore, the suffix is meaningful to preprocessing.

    – Eric Postpischil
    4 hours ago




    1




    1





    As I said, I am splitting hairs rather finely. In particular, I am placing the evaluation of the expression outside the scope of the preprocessor proper, on account of (1) it operating on tokens, not preprocessing tokens, and (2) it being governed by the regular C rules for evaluation, as opposed to special rules pertaining to the preprocessor. This is appropos to the question, which expresses surprise about the C syntax for integer constants being recognized and handled. Yes it is, because no other is defined for the purpose.

    – John Bollinger
    4 hours ago






    As I said, I am splitting hairs rather finely. In particular, I am placing the evaluation of the expression outside the scope of the preprocessor proper, on account of (1) it operating on tokens, not preprocessing tokens, and (2) it being governed by the regular C rules for evaluation, as opposed to special rules pertaining to the preprocessor. This is appropos to the question, which expresses surprise about the C syntax for integer constants being recognized and handled. Yes it is, because no other is defined for the purpose.

    – John Bollinger
    4 hours ago














    4














    As I noted in a comment, this is defined in the C standard. Here's the complete text of §6.10.1 ¶4 (and the two footnotes):




    C11 §6.10.1 Conditional inclusion



    ¶4 Prior to evaluation, macro invocations in the list of preprocessing tokens that will become the controlling constant expression are replaced (except for those macro names modified by the defined unary operator), just as in normal text. If the token defined is generated as a result of this replacement process or use of the defined unary operator does not match one of the two specified forms prior to macro replacement, the behavior is undefined. 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. The resulting tokens compose the controlling constant expression which is evaluated according to the rules of 6.6. For the purposes of this token conversion and evaluation, all signed integer types and all unsigned integer types act as if they have the same representation as, respectively, the types intmax_t and uintmax_t defined in the header <stdint.h>.167) This includes interpreting character constants, which may involve converting escape sequences into execution character set members. Whether the numeric value for these character constants matches the value obtained when an identical character constant occurs in an expression (other than within a #if or #elif directive) is implementation-defined.168) Also, whether a single-character character constant may have a negative value is implementation-defined.



    167 167) Thus, on an implementation where INT_MAX is 0x7FFF and UINT_MAX is 0xFFFF, the constant 0x8000 is signed and positive within a #if expression even though it would be unsigned in translation phase 7.



    168 Thus, the constant expression in the following #if directive and if statement is not guaranteed to evaluate to the same value in these two contexts.



    #if 'z' - 'a' == 25
    if ('z' - 'a' == 25)



    Section 6.6 is §6.6 Constant expressions, which details the differences between the full expressions in section §6.5 Expressions and constant expressions.



    In effect, the preprocessor largely ignores the suffixes. Hexadecimal constants are unsigned. The results you show are to be expected on a machine where intmax_t and uintmax_t are 64-bit quantities. If the limits on the intmax_t and uintmax_t were larger, some of the expressions might change.






    share|improve this answer




















    • 1





      The preprocessor cannot ignore the suffixes. It might ignore their width effects, but not the signedness.

      – Eric Postpischil
      5 hours ago















    4














    As I noted in a comment, this is defined in the C standard. Here's the complete text of §6.10.1 ¶4 (and the two footnotes):




    C11 §6.10.1 Conditional inclusion



    ¶4 Prior to evaluation, macro invocations in the list of preprocessing tokens that will become the controlling constant expression are replaced (except for those macro names modified by the defined unary operator), just as in normal text. If the token defined is generated as a result of this replacement process or use of the defined unary operator does not match one of the two specified forms prior to macro replacement, the behavior is undefined. 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. The resulting tokens compose the controlling constant expression which is evaluated according to the rules of 6.6. For the purposes of this token conversion and evaluation, all signed integer types and all unsigned integer types act as if they have the same representation as, respectively, the types intmax_t and uintmax_t defined in the header <stdint.h>.167) This includes interpreting character constants, which may involve converting escape sequences into execution character set members. Whether the numeric value for these character constants matches the value obtained when an identical character constant occurs in an expression (other than within a #if or #elif directive) is implementation-defined.168) Also, whether a single-character character constant may have a negative value is implementation-defined.



    167 167) Thus, on an implementation where INT_MAX is 0x7FFF and UINT_MAX is 0xFFFF, the constant 0x8000 is signed and positive within a #if expression even though it would be unsigned in translation phase 7.



    168 Thus, the constant expression in the following #if directive and if statement is not guaranteed to evaluate to the same value in these two contexts.



    #if 'z' - 'a' == 25
    if ('z' - 'a' == 25)



    Section 6.6 is §6.6 Constant expressions, which details the differences between the full expressions in section §6.5 Expressions and constant expressions.



    In effect, the preprocessor largely ignores the suffixes. Hexadecimal constants are unsigned. The results you show are to be expected on a machine where intmax_t and uintmax_t are 64-bit quantities. If the limits on the intmax_t and uintmax_t were larger, some of the expressions might change.






    share|improve this answer




















    • 1





      The preprocessor cannot ignore the suffixes. It might ignore their width effects, but not the signedness.

      – Eric Postpischil
      5 hours ago













    4












    4








    4







    As I noted in a comment, this is defined in the C standard. Here's the complete text of §6.10.1 ¶4 (and the two footnotes):




    C11 §6.10.1 Conditional inclusion



    ¶4 Prior to evaluation, macro invocations in the list of preprocessing tokens that will become the controlling constant expression are replaced (except for those macro names modified by the defined unary operator), just as in normal text. If the token defined is generated as a result of this replacement process or use of the defined unary operator does not match one of the two specified forms prior to macro replacement, the behavior is undefined. 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. The resulting tokens compose the controlling constant expression which is evaluated according to the rules of 6.6. For the purposes of this token conversion and evaluation, all signed integer types and all unsigned integer types act as if they have the same representation as, respectively, the types intmax_t and uintmax_t defined in the header <stdint.h>.167) This includes interpreting character constants, which may involve converting escape sequences into execution character set members. Whether the numeric value for these character constants matches the value obtained when an identical character constant occurs in an expression (other than within a #if or #elif directive) is implementation-defined.168) Also, whether a single-character character constant may have a negative value is implementation-defined.



    167 167) Thus, on an implementation where INT_MAX is 0x7FFF and UINT_MAX is 0xFFFF, the constant 0x8000 is signed and positive within a #if expression even though it would be unsigned in translation phase 7.



    168 Thus, the constant expression in the following #if directive and if statement is not guaranteed to evaluate to the same value in these two contexts.



    #if 'z' - 'a' == 25
    if ('z' - 'a' == 25)



    Section 6.6 is §6.6 Constant expressions, which details the differences between the full expressions in section §6.5 Expressions and constant expressions.



    In effect, the preprocessor largely ignores the suffixes. Hexadecimal constants are unsigned. The results you show are to be expected on a machine where intmax_t and uintmax_t are 64-bit quantities. If the limits on the intmax_t and uintmax_t were larger, some of the expressions might change.






    share|improve this answer















    As I noted in a comment, this is defined in the C standard. Here's the complete text of §6.10.1 ¶4 (and the two footnotes):




    C11 §6.10.1 Conditional inclusion



    ¶4 Prior to evaluation, macro invocations in the list of preprocessing tokens that will become the controlling constant expression are replaced (except for those macro names modified by the defined unary operator), just as in normal text. If the token defined is generated as a result of this replacement process or use of the defined unary operator does not match one of the two specified forms prior to macro replacement, the behavior is undefined. 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. The resulting tokens compose the controlling constant expression which is evaluated according to the rules of 6.6. For the purposes of this token conversion and evaluation, all signed integer types and all unsigned integer types act as if they have the same representation as, respectively, the types intmax_t and uintmax_t defined in the header <stdint.h>.167) This includes interpreting character constants, which may involve converting escape sequences into execution character set members. Whether the numeric value for these character constants matches the value obtained when an identical character constant occurs in an expression (other than within a #if or #elif directive) is implementation-defined.168) Also, whether a single-character character constant may have a negative value is implementation-defined.



    167 167) Thus, on an implementation where INT_MAX is 0x7FFF and UINT_MAX is 0xFFFF, the constant 0x8000 is signed and positive within a #if expression even though it would be unsigned in translation phase 7.



    168 Thus, the constant expression in the following #if directive and if statement is not guaranteed to evaluate to the same value in these two contexts.



    #if 'z' - 'a' == 25
    if ('z' - 'a' == 25)



    Section 6.6 is §6.6 Constant expressions, which details the differences between the full expressions in section §6.5 Expressions and constant expressions.



    In effect, the preprocessor largely ignores the suffixes. Hexadecimal constants are unsigned. The results you show are to be expected on a machine where intmax_t and uintmax_t are 64-bit quantities. If the limits on the intmax_t and uintmax_t were larger, some of the expressions might change.







    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited 3 hours ago

























    answered 5 hours ago









    Jonathan LefflerJonathan Leffler

    580k966941049




    580k966941049







    • 1





      The preprocessor cannot ignore the suffixes. It might ignore their width effects, but not the signedness.

      – Eric Postpischil
      5 hours ago












    • 1





      The preprocessor cannot ignore the suffixes. It might ignore their width effects, but not the signedness.

      – Eric Postpischil
      5 hours ago







    1




    1





    The preprocessor cannot ignore the suffixes. It might ignore their width effects, but not the signedness.

    – Eric Postpischil
    5 hours ago





    The preprocessor cannot ignore the suffixes. It might ignore their width effects, but not the signedness.

    – Eric Postpischil
    5 hours ago











    3














    C 2018 6.10.1 deals with conditional inclusion (#if and related statements and the defined operator). Paragraph 1 says:




    The expression that controls conditional inclusion shall be an integer constant expression except that: identifiers (including those lexically identical to keywords) are interpreted as described below; and it may contain unary operator expressions of the form



    defined identifier



    or



    defined ( identifier )




    Integer constant expression is defined in 6.6 6:




    An integer constant expression shall have integer type and shall only have operands that are integer constants, enumeration constants, character constants, sizeof expressions whose results are integer constants, _Alignof expressions, and floating constants that are the immediate operands of casts. Cast operators in an integer constant expression shall only convert arithmetic types to integer types, except as part of an operand to the sizeof or _Alignof operator.




    That paragraph is for C generally, not just the preprocessor. So the expressions that can appear in #if statements are the same as the integer constant expressions that can appear generally in C. However, as stated in the quote above, sizeof and _Alignof are just identifiers; they are not recognized as C operators. In particular, 6.10.1 4 tells us:




    … 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,…




    So, where sizeof or _Alignof appear in a #if expression, it becomes 0. Thus, a #if expression can only have operands that are constants and defined expressions.



    Paragraph 4 goes on to say:




    … The resulting tokens compose the controlling constant expression which is evaluated according to the rules of 6.6. For the purposes of this token conversion and evaluation, all signed integer types and all unsigned integer types act as if they have the same representation as, respectively, the types intmax_t and uintmax_t defined in the header <stdint.h>.…




    6.6 is the section for constant expressions.



    So, the compiler will accept integer suffixes in #if expressions, and that does not depend on the C implementation (for the suffixes required in the core C language; implementations could allow extensions). However, all the arithmetic will be performed using intmax_t or uintmax_t, and those do depend on the implementation. If your expressions do not depend on the width of integers above the minimum required1, they should be evaluated the same in any C implementation.



    Additionally, paragraph 4 goes on to say there may be some variations with character constants and values, which I omit here as it is not relevant to this question.



    Footnote



    1intmax_t designates a signed type capable of representing any value of any signed integer type (7.20.1.5 1), and long long int is a signed type that must be at least 64 bits (5.2.4.2.1 1), so any conforming C implementation must provide 64-bit integer arithmetic in the preprocessor.






    share|improve this answer

























    • About So the expressions that can appear in #if statements are the same as the integer constant expressions that can appear generally in C.: I guess not quite. A footnote in chapter "Constant expressions" reads Further constraints that apply to the integer constant expressions used in conditional-inclusion preprocessing directives are discussed in 6.10.1. and then in a footnote of 6.10.1: 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.

      – Michi
      3 hours ago















    3














    C 2018 6.10.1 deals with conditional inclusion (#if and related statements and the defined operator). Paragraph 1 says:




    The expression that controls conditional inclusion shall be an integer constant expression except that: identifiers (including those lexically identical to keywords) are interpreted as described below; and it may contain unary operator expressions of the form



    defined identifier



    or



    defined ( identifier )




    Integer constant expression is defined in 6.6 6:




    An integer constant expression shall have integer type and shall only have operands that are integer constants, enumeration constants, character constants, sizeof expressions whose results are integer constants, _Alignof expressions, and floating constants that are the immediate operands of casts. Cast operators in an integer constant expression shall only convert arithmetic types to integer types, except as part of an operand to the sizeof or _Alignof operator.




    That paragraph is for C generally, not just the preprocessor. So the expressions that can appear in #if statements are the same as the integer constant expressions that can appear generally in C. However, as stated in the quote above, sizeof and _Alignof are just identifiers; they are not recognized as C operators. In particular, 6.10.1 4 tells us:




    … 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,…




    So, where sizeof or _Alignof appear in a #if expression, it becomes 0. Thus, a #if expression can only have operands that are constants and defined expressions.



    Paragraph 4 goes on to say:




    … The resulting tokens compose the controlling constant expression which is evaluated according to the rules of 6.6. For the purposes of this token conversion and evaluation, all signed integer types and all unsigned integer types act as if they have the same representation as, respectively, the types intmax_t and uintmax_t defined in the header <stdint.h>.…




    6.6 is the section for constant expressions.



    So, the compiler will accept integer suffixes in #if expressions, and that does not depend on the C implementation (for the suffixes required in the core C language; implementations could allow extensions). However, all the arithmetic will be performed using intmax_t or uintmax_t, and those do depend on the implementation. If your expressions do not depend on the width of integers above the minimum required1, they should be evaluated the same in any C implementation.



    Additionally, paragraph 4 goes on to say there may be some variations with character constants and values, which I omit here as it is not relevant to this question.



    Footnote



    1intmax_t designates a signed type capable of representing any value of any signed integer type (7.20.1.5 1), and long long int is a signed type that must be at least 64 bits (5.2.4.2.1 1), so any conforming C implementation must provide 64-bit integer arithmetic in the preprocessor.






    share|improve this answer

























    • About So the expressions that can appear in #if statements are the same as the integer constant expressions that can appear generally in C.: I guess not quite. A footnote in chapter "Constant expressions" reads Further constraints that apply to the integer constant expressions used in conditional-inclusion preprocessing directives are discussed in 6.10.1. and then in a footnote of 6.10.1: 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.

      – Michi
      3 hours ago













    3












    3








    3







    C 2018 6.10.1 deals with conditional inclusion (#if and related statements and the defined operator). Paragraph 1 says:




    The expression that controls conditional inclusion shall be an integer constant expression except that: identifiers (including those lexically identical to keywords) are interpreted as described below; and it may contain unary operator expressions of the form



    defined identifier



    or



    defined ( identifier )




    Integer constant expression is defined in 6.6 6:




    An integer constant expression shall have integer type and shall only have operands that are integer constants, enumeration constants, character constants, sizeof expressions whose results are integer constants, _Alignof expressions, and floating constants that are the immediate operands of casts. Cast operators in an integer constant expression shall only convert arithmetic types to integer types, except as part of an operand to the sizeof or _Alignof operator.




    That paragraph is for C generally, not just the preprocessor. So the expressions that can appear in #if statements are the same as the integer constant expressions that can appear generally in C. However, as stated in the quote above, sizeof and _Alignof are just identifiers; they are not recognized as C operators. In particular, 6.10.1 4 tells us:




    … 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,…




    So, where sizeof or _Alignof appear in a #if expression, it becomes 0. Thus, a #if expression can only have operands that are constants and defined expressions.



    Paragraph 4 goes on to say:




    … The resulting tokens compose the controlling constant expression which is evaluated according to the rules of 6.6. For the purposes of this token conversion and evaluation, all signed integer types and all unsigned integer types act as if they have the same representation as, respectively, the types intmax_t and uintmax_t defined in the header <stdint.h>.…




    6.6 is the section for constant expressions.



    So, the compiler will accept integer suffixes in #if expressions, and that does not depend on the C implementation (for the suffixes required in the core C language; implementations could allow extensions). However, all the arithmetic will be performed using intmax_t or uintmax_t, and those do depend on the implementation. If your expressions do not depend on the width of integers above the minimum required1, they should be evaluated the same in any C implementation.



    Additionally, paragraph 4 goes on to say there may be some variations with character constants and values, which I omit here as it is not relevant to this question.



    Footnote



    1intmax_t designates a signed type capable of representing any value of any signed integer type (7.20.1.5 1), and long long int is a signed type that must be at least 64 bits (5.2.4.2.1 1), so any conforming C implementation must provide 64-bit integer arithmetic in the preprocessor.






    share|improve this answer















    C 2018 6.10.1 deals with conditional inclusion (#if and related statements and the defined operator). Paragraph 1 says:




    The expression that controls conditional inclusion shall be an integer constant expression except that: identifiers (including those lexically identical to keywords) are interpreted as described below; and it may contain unary operator expressions of the form



    defined identifier



    or



    defined ( identifier )




    Integer constant expression is defined in 6.6 6:




    An integer constant expression shall have integer type and shall only have operands that are integer constants, enumeration constants, character constants, sizeof expressions whose results are integer constants, _Alignof expressions, and floating constants that are the immediate operands of casts. Cast operators in an integer constant expression shall only convert arithmetic types to integer types, except as part of an operand to the sizeof or _Alignof operator.




    That paragraph is for C generally, not just the preprocessor. So the expressions that can appear in #if statements are the same as the integer constant expressions that can appear generally in C. However, as stated in the quote above, sizeof and _Alignof are just identifiers; they are not recognized as C operators. In particular, 6.10.1 4 tells us:




    … 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,…




    So, where sizeof or _Alignof appear in a #if expression, it becomes 0. Thus, a #if expression can only have operands that are constants and defined expressions.



    Paragraph 4 goes on to say:




    … The resulting tokens compose the controlling constant expression which is evaluated according to the rules of 6.6. For the purposes of this token conversion and evaluation, all signed integer types and all unsigned integer types act as if they have the same representation as, respectively, the types intmax_t and uintmax_t defined in the header <stdint.h>.…




    6.6 is the section for constant expressions.



    So, the compiler will accept integer suffixes in #if expressions, and that does not depend on the C implementation (for the suffixes required in the core C language; implementations could allow extensions). However, all the arithmetic will be performed using intmax_t or uintmax_t, and those do depend on the implementation. If your expressions do not depend on the width of integers above the minimum required1, they should be evaluated the same in any C implementation.



    Additionally, paragraph 4 goes on to say there may be some variations with character constants and values, which I omit here as it is not relevant to this question.



    Footnote



    1intmax_t designates a signed type capable of representing any value of any signed integer type (7.20.1.5 1), and long long int is a signed type that must be at least 64 bits (5.2.4.2.1 1), so any conforming C implementation must provide 64-bit integer arithmetic in the preprocessor.







    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited 5 hours ago

























    answered 5 hours ago









    Eric PostpischilEric Postpischil

    83.7k891171




    83.7k891171












    • About So the expressions that can appear in #if statements are the same as the integer constant expressions that can appear generally in C.: I guess not quite. A footnote in chapter "Constant expressions" reads Further constraints that apply to the integer constant expressions used in conditional-inclusion preprocessing directives are discussed in 6.10.1. and then in a footnote of 6.10.1: 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.

      – Michi
      3 hours ago

















    • About So the expressions that can appear in #if statements are the same as the integer constant expressions that can appear generally in C.: I guess not quite. A footnote in chapter "Constant expressions" reads Further constraints that apply to the integer constant expressions used in conditional-inclusion preprocessing directives are discussed in 6.10.1. and then in a footnote of 6.10.1: 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.

      – Michi
      3 hours ago
















    About So the expressions that can appear in #if statements are the same as the integer constant expressions that can appear generally in C.: I guess not quite. A footnote in chapter "Constant expressions" reads Further constraints that apply to the integer constant expressions used in conditional-inclusion preprocessing directives are discussed in 6.10.1. and then in a footnote of 6.10.1: 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.

    – Michi
    3 hours ago





    About So the expressions that can appear in #if statements are the same as the integer constant expressions that can appear generally in C.: I guess not quite. A footnote in chapter "Constant expressions" reads Further constraints that apply to the integer constant expressions used in conditional-inclusion preprocessing directives are discussed in 6.10.1. and then in a footnote of 6.10.1: 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.

    – Michi
    3 hours ago











    0














    TLDR dumbed down version:



    l and ll are effectively (not literally!) ignored by the preprocessor conditionals (basically, everything is treated as if it had a ll suffix), however u is considered (normally, as for every C integer constant)!



    After reading all the marvelous answers, I created some more examples that reveal some expected but yet interesting behavior:



    #include <stdio.h>

    int main()

    #if (1 - 2u > 0) // If one operand is unsigned, the result is unsigned.
    // Usual implicit type conversion.
    printf("1 - 2u > 0n");
    #endif

    #if (0 < 0xFFFFFFFFFFFFFFFF)
    printf("0 < 0xFFFFFFFFFFFFFFFFn");
    #endif

    #if (-1 < 0)
    printf("-1 < 0n");
    #endif

    #if (-1 < 0xFFFFFFFFFFFFFFFF)
    printf("-1 < 0xFFFFFFFFFFFFFFFFn"); // nope
    #elif (-1 > 0xFFFFFFFFFFFFFFFF)
    printf("-1 > 0xFFFFFFFFFFFFFFFFn"); // nope, obviously
    #endif

    #if (-1 == 0xFFFFFFFFFFFFFFFF)
    printf("-1 == 0xFFFFFFFFFFFFFFFF (!!!)n");
    #endif



    With this output:



    1 - 2u > 0
    0 < 0xFFFFFFFFFFFFFFFF
    -1 < 0
    -1 == 0xFFFFFFFFFFFFFFFF (!!!)





    share|improve this answer



























      0














      TLDR dumbed down version:



      l and ll are effectively (not literally!) ignored by the preprocessor conditionals (basically, everything is treated as if it had a ll suffix), however u is considered (normally, as for every C integer constant)!



      After reading all the marvelous answers, I created some more examples that reveal some expected but yet interesting behavior:



      #include <stdio.h>

      int main()

      #if (1 - 2u > 0) // If one operand is unsigned, the result is unsigned.
      // Usual implicit type conversion.
      printf("1 - 2u > 0n");
      #endif

      #if (0 < 0xFFFFFFFFFFFFFFFF)
      printf("0 < 0xFFFFFFFFFFFFFFFFn");
      #endif

      #if (-1 < 0)
      printf("-1 < 0n");
      #endif

      #if (-1 < 0xFFFFFFFFFFFFFFFF)
      printf("-1 < 0xFFFFFFFFFFFFFFFFn"); // nope
      #elif (-1 > 0xFFFFFFFFFFFFFFFF)
      printf("-1 > 0xFFFFFFFFFFFFFFFFn"); // nope, obviously
      #endif

      #if (-1 == 0xFFFFFFFFFFFFFFFF)
      printf("-1 == 0xFFFFFFFFFFFFFFFF (!!!)n");
      #endif



      With this output:



      1 - 2u > 0
      0 < 0xFFFFFFFFFFFFFFFF
      -1 < 0
      -1 == 0xFFFFFFFFFFFFFFFF (!!!)





      share|improve this answer

























        0












        0








        0







        TLDR dumbed down version:



        l and ll are effectively (not literally!) ignored by the preprocessor conditionals (basically, everything is treated as if it had a ll suffix), however u is considered (normally, as for every C integer constant)!



        After reading all the marvelous answers, I created some more examples that reveal some expected but yet interesting behavior:



        #include <stdio.h>

        int main()

        #if (1 - 2u > 0) // If one operand is unsigned, the result is unsigned.
        // Usual implicit type conversion.
        printf("1 - 2u > 0n");
        #endif

        #if (0 < 0xFFFFFFFFFFFFFFFF)
        printf("0 < 0xFFFFFFFFFFFFFFFFn");
        #endif

        #if (-1 < 0)
        printf("-1 < 0n");
        #endif

        #if (-1 < 0xFFFFFFFFFFFFFFFF)
        printf("-1 < 0xFFFFFFFFFFFFFFFFn"); // nope
        #elif (-1 > 0xFFFFFFFFFFFFFFFF)
        printf("-1 > 0xFFFFFFFFFFFFFFFFn"); // nope, obviously
        #endif

        #if (-1 == 0xFFFFFFFFFFFFFFFF)
        printf("-1 == 0xFFFFFFFFFFFFFFFF (!!!)n");
        #endif



        With this output:



        1 - 2u > 0
        0 < 0xFFFFFFFFFFFFFFFF
        -1 < 0
        -1 == 0xFFFFFFFFFFFFFFFF (!!!)





        share|improve this answer













        TLDR dumbed down version:



        l and ll are effectively (not literally!) ignored by the preprocessor conditionals (basically, everything is treated as if it had a ll suffix), however u is considered (normally, as for every C integer constant)!



        After reading all the marvelous answers, I created some more examples that reveal some expected but yet interesting behavior:



        #include <stdio.h>

        int main()

        #if (1 - 2u > 0) // If one operand is unsigned, the result is unsigned.
        // Usual implicit type conversion.
        printf("1 - 2u > 0n");
        #endif

        #if (0 < 0xFFFFFFFFFFFFFFFF)
        printf("0 < 0xFFFFFFFFFFFFFFFFn");
        #endif

        #if (-1 < 0)
        printf("-1 < 0n");
        #endif

        #if (-1 < 0xFFFFFFFFFFFFFFFF)
        printf("-1 < 0xFFFFFFFFFFFFFFFFn"); // nope
        #elif (-1 > 0xFFFFFFFFFFFFFFFF)
        printf("-1 > 0xFFFFFFFFFFFFFFFFn"); // nope, obviously
        #endif

        #if (-1 == 0xFFFFFFFFFFFFFFFF)
        printf("-1 == 0xFFFFFFFFFFFFFFFF (!!!)n");
        #endif



        With this output:



        1 - 2u > 0
        0 < 0xFFFFFFFFFFFFFFFF
        -1 < 0
        -1 == 0xFFFFFFFFFFFFFFFF (!!!)






        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered 2 hours ago









        MichiMichi

        414317




        414317



























            draft saved

            draft discarded
















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid


            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.

            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f56244247%2fto-which-degree-does-the-c-preprocessor-regard-integer-literal-suffixes%23new-answer', 'question_page');

            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            Invision Community Contents History See also References External links Navigation menuProprietaryinvisioncommunity.comIPS Community ForumsIPS Community Forumsthis blog entry"License Changes, IP.Board 3.4, and the Future""Interview -- Matt Mecham of Ibforums""CEO Invision Power Board, Matt Mecham Is a Liar, Thief!"IPB License Explanation 1.3, 1.3.1, 2.0, and 2.1ArchivedSecurity Fixes, Updates And Enhancements For IPB 1.3.1Archived"New Demo Accounts - Invision Power Services"the original"New Default Skin"the original"Invision Power Board 3.0.0 and Applications Released"the original"Archived copy"the original"Perpetual licenses being done away with""Release Notes - Invision Power Services""Introducing: IPS Community Suite 4!"Invision Community Release Notes

            Canceling a color specificationRandomly assigning color to Graphics3D objects?Default color for Filling in Mathematica 9Coloring specific elements of sets with a prime modified order in an array plotHow to pick a color differing significantly from the colors already in a given color list?Detection of the text colorColor numbers based on their valueCan color schemes for use with ColorData include opacity specification?My dynamic color schemes

            Ласкавець круглолистий Зміст Опис | Поширення | Галерея | Примітки | Посилання | Навігаційне меню58171138361-22960890446Bupleurum rotundifoliumEuro+Med PlantbasePlants of the World Online — Kew ScienceGermplasm Resources Information Network (GRIN)Ласкавецькн. VI : Літери Ком — Левиправивши або дописавши її