What is the point of the {U,}INTn_C macros in stdint.h?











up vote
3
down vote

favorite












When are these macros actually needed?



My systems (gcc/glibc/linux/x86_64) stdint.h uses (__-prefixed) variant of these to define:



# define INT64_MIN      (-__INT64_C(9223372036854775807)-1)
# define INT64_MAX (__INT64_C(9223372036854775807))
# define UINT64_MAX (__UINT64_C(18446744073709551615))
# define INT_LEAST64_MIN (-__INT64_C(9223372036854775807)-1)
# define INT_LEAST64_MAX (__INT64_C(9223372036854775807))
# define UINT_LEAST64_MAX (__UINT64_C(18446744073709551615))
# define INT_FAST64_MIN (-__INT64_C(9223372036854775807)-1)
# define INT_FAST64_MAX (__INT64_C(9223372036854775807))
# define UINT_FAST64_MAX (__UINT64_C(18446744073709551615))
# define INTMAX_MIN (-__INT64_C(9223372036854775807)-1)
# define INTMAX_MAX (__INT64_C(9223372036854775807))
# define UINTMAX_MAX (__UINT64_C(18446744073709551615))


Yet for limits.h it seems to make do with:



#   define LONG_MAX 9223372036854775807L
# define ULONG_MAX 18446744073709551615UL


Why can't stdint.h forget about the _C macros and simply do:



#   define INT_LEAST64_MAX  9223372036854775807 //let it grow as needed
# define UINT_LEAST64_MAX 18446744073709551615U //just the U


What are the use cases for these macros?



The only one I could think of is where I want a sufficiently wide constant usable in cpp conditionals and at the same time I don't want it too wide:



//C guarantees longs are at least 32 bits wide
#define THREE_GIGS_BUT_MAYBE_TOO_WIDE (1L<<30)
#define THREE_GIGS (INT32_C(1)<<30) //possibly narrower than the define above









share|improve this question
























  • Most likely because LL is “at least 64bit” but not necessarily exactly 64bit. And different platforms may have different definitions so a macro makes it simple to change things without changing the common headers.
    – Sami Kuhmonen
    Nov 10 at 20:23










  • System headers are not necessarily designed exclusively for standards conforming C compilers.
    – n.m.
    Nov 10 at 21:11










  • Possible duplicate of When should I use UINT32_C(), INT32_C(),... macros in C?
    – Giovanni Cerretani
    Nov 10 at 22:06















up vote
3
down vote

favorite












When are these macros actually needed?



My systems (gcc/glibc/linux/x86_64) stdint.h uses (__-prefixed) variant of these to define:



# define INT64_MIN      (-__INT64_C(9223372036854775807)-1)
# define INT64_MAX (__INT64_C(9223372036854775807))
# define UINT64_MAX (__UINT64_C(18446744073709551615))
# define INT_LEAST64_MIN (-__INT64_C(9223372036854775807)-1)
# define INT_LEAST64_MAX (__INT64_C(9223372036854775807))
# define UINT_LEAST64_MAX (__UINT64_C(18446744073709551615))
# define INT_FAST64_MIN (-__INT64_C(9223372036854775807)-1)
# define INT_FAST64_MAX (__INT64_C(9223372036854775807))
# define UINT_FAST64_MAX (__UINT64_C(18446744073709551615))
# define INTMAX_MIN (-__INT64_C(9223372036854775807)-1)
# define INTMAX_MAX (__INT64_C(9223372036854775807))
# define UINTMAX_MAX (__UINT64_C(18446744073709551615))


Yet for limits.h it seems to make do with:



#   define LONG_MAX 9223372036854775807L
# define ULONG_MAX 18446744073709551615UL


Why can't stdint.h forget about the _C macros and simply do:



#   define INT_LEAST64_MAX  9223372036854775807 //let it grow as needed
# define UINT_LEAST64_MAX 18446744073709551615U //just the U


What are the use cases for these macros?



The only one I could think of is where I want a sufficiently wide constant usable in cpp conditionals and at the same time I don't want it too wide:



//C guarantees longs are at least 32 bits wide
#define THREE_GIGS_BUT_MAYBE_TOO_WIDE (1L<<30)
#define THREE_GIGS (INT32_C(1)<<30) //possibly narrower than the define above









share|improve this question
























  • Most likely because LL is “at least 64bit” but not necessarily exactly 64bit. And different platforms may have different definitions so a macro makes it simple to change things without changing the common headers.
    – Sami Kuhmonen
    Nov 10 at 20:23










  • System headers are not necessarily designed exclusively for standards conforming C compilers.
    – n.m.
    Nov 10 at 21:11










  • Possible duplicate of When should I use UINT32_C(), INT32_C(),... macros in C?
    – Giovanni Cerretani
    Nov 10 at 22:06













up vote
3
down vote

favorite









up vote
3
down vote

favorite











When are these macros actually needed?



My systems (gcc/glibc/linux/x86_64) stdint.h uses (__-prefixed) variant of these to define:



# define INT64_MIN      (-__INT64_C(9223372036854775807)-1)
# define INT64_MAX (__INT64_C(9223372036854775807))
# define UINT64_MAX (__UINT64_C(18446744073709551615))
# define INT_LEAST64_MIN (-__INT64_C(9223372036854775807)-1)
# define INT_LEAST64_MAX (__INT64_C(9223372036854775807))
# define UINT_LEAST64_MAX (__UINT64_C(18446744073709551615))
# define INT_FAST64_MIN (-__INT64_C(9223372036854775807)-1)
# define INT_FAST64_MAX (__INT64_C(9223372036854775807))
# define UINT_FAST64_MAX (__UINT64_C(18446744073709551615))
# define INTMAX_MIN (-__INT64_C(9223372036854775807)-1)
# define INTMAX_MAX (__INT64_C(9223372036854775807))
# define UINTMAX_MAX (__UINT64_C(18446744073709551615))


Yet for limits.h it seems to make do with:



#   define LONG_MAX 9223372036854775807L
# define ULONG_MAX 18446744073709551615UL


Why can't stdint.h forget about the _C macros and simply do:



#   define INT_LEAST64_MAX  9223372036854775807 //let it grow as needed
# define UINT_LEAST64_MAX 18446744073709551615U //just the U


What are the use cases for these macros?



The only one I could think of is where I want a sufficiently wide constant usable in cpp conditionals and at the same time I don't want it too wide:



//C guarantees longs are at least 32 bits wide
#define THREE_GIGS_BUT_MAYBE_TOO_WIDE (1L<<30)
#define THREE_GIGS (INT32_C(1)<<30) //possibly narrower than the define above









share|improve this question















When are these macros actually needed?



My systems (gcc/glibc/linux/x86_64) stdint.h uses (__-prefixed) variant of these to define:



# define INT64_MIN      (-__INT64_C(9223372036854775807)-1)
# define INT64_MAX (__INT64_C(9223372036854775807))
# define UINT64_MAX (__UINT64_C(18446744073709551615))
# define INT_LEAST64_MIN (-__INT64_C(9223372036854775807)-1)
# define INT_LEAST64_MAX (__INT64_C(9223372036854775807))
# define UINT_LEAST64_MAX (__UINT64_C(18446744073709551615))
# define INT_FAST64_MIN (-__INT64_C(9223372036854775807)-1)
# define INT_FAST64_MAX (__INT64_C(9223372036854775807))
# define UINT_FAST64_MAX (__UINT64_C(18446744073709551615))
# define INTMAX_MIN (-__INT64_C(9223372036854775807)-1)
# define INTMAX_MAX (__INT64_C(9223372036854775807))
# define UINTMAX_MAX (__UINT64_C(18446744073709551615))


Yet for limits.h it seems to make do with:



#   define LONG_MAX 9223372036854775807L
# define ULONG_MAX 18446744073709551615UL


Why can't stdint.h forget about the _C macros and simply do:



#   define INT_LEAST64_MAX  9223372036854775807 //let it grow as needed
# define UINT_LEAST64_MAX 18446744073709551615U //just the U


What are the use cases for these macros?



The only one I could think of is where I want a sufficiently wide constant usable in cpp conditionals and at the same time I don't want it too wide:



//C guarantees longs are at least 32 bits wide
#define THREE_GIGS_BUT_MAYBE_TOO_WIDE (1L<<30)
#define THREE_GIGS (INT32_C(1)<<30) //possibly narrower than the define above






c language-lawyer






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 10 at 20:53









Jonathan Leffler

554k886581012




554k886581012










asked Nov 10 at 20:13









PSkocik

31k54568




31k54568












  • Most likely because LL is “at least 64bit” but not necessarily exactly 64bit. And different platforms may have different definitions so a macro makes it simple to change things without changing the common headers.
    – Sami Kuhmonen
    Nov 10 at 20:23










  • System headers are not necessarily designed exclusively for standards conforming C compilers.
    – n.m.
    Nov 10 at 21:11










  • Possible duplicate of When should I use UINT32_C(), INT32_C(),... macros in C?
    – Giovanni Cerretani
    Nov 10 at 22:06


















  • Most likely because LL is “at least 64bit” but not necessarily exactly 64bit. And different platforms may have different definitions so a macro makes it simple to change things without changing the common headers.
    – Sami Kuhmonen
    Nov 10 at 20:23










  • System headers are not necessarily designed exclusively for standards conforming C compilers.
    – n.m.
    Nov 10 at 21:11










  • Possible duplicate of When should I use UINT32_C(), INT32_C(),... macros in C?
    – Giovanni Cerretani
    Nov 10 at 22:06
















Most likely because LL is “at least 64bit” but not necessarily exactly 64bit. And different platforms may have different definitions so a macro makes it simple to change things without changing the common headers.
– Sami Kuhmonen
Nov 10 at 20:23




Most likely because LL is “at least 64bit” but not necessarily exactly 64bit. And different platforms may have different definitions so a macro makes it simple to change things without changing the common headers.
– Sami Kuhmonen
Nov 10 at 20:23












System headers are not necessarily designed exclusively for standards conforming C compilers.
– n.m.
Nov 10 at 21:11




System headers are not necessarily designed exclusively for standards conforming C compilers.
– n.m.
Nov 10 at 21:11












Possible duplicate of When should I use UINT32_C(), INT32_C(),... macros in C?
– Giovanni Cerretani
Nov 10 at 22:06




Possible duplicate of When should I use UINT32_C(), INT32_C(),... macros in C?
– Giovanni Cerretani
Nov 10 at 22:06












2 Answers
2






active

oldest

votes

















up vote
2
down vote













The point of e.g. __UINT64_C(x) seems to be to attach the correct kind of suffix to x.



In this way, the implementer of the C standard library header files are able to separate the numerical constants (which are the same on all platforms) from the suffixes (which depend on the integer size).



For example, when building a 64-bit executable, the __UINT64_C(x) would evaluate to x ## UL, while when building a 32-bit executable, it would evaluate to x ## ULL.



Edit: as @PSkocik points out, for signed integers this macro is not necessary. My guess is that it is still present as (1) the suffix is necessary for unsigned values and (2) the authors wanted to keep the code consistent for signed and unsigned constants.






share|improve this answer























  • 9223372036854775807 doesn't need any suffix to be typed long on an LP64 platform. And if it doesn't fit long it'll be automatically long long (as per port70.net/~nsz/c/c11/n1570.html#6.4.4.1p5). And it must fit at least long long because long long is required to be present at least 64 bits wide.
    – PSkocik
    Nov 10 at 20:41


















up vote
1
down vote














What is the point of the {U,}INTn_C macros in <stdint.h>?




They insure a minimal type width and sign-ness for a constant.



They "expand to an integer constant expression corresponding to the type (u)int_leastN_t."



123 << 50                // likely int overflow (UB)
INT32_C(123) << 50 // likely int overflow (UB)
INT64_C(123) << 50 // well defined.
INT32_C(123)*2000000000 // likely int overflow (UB)
UINT32_C(123)*2000000000 // well defined - even though it may mathematically overflow


Useful when defining computed constants.



// well defined, but the wrong product when unsigned is 32-bit
#define TBYTE (1024u*1024*1024*1024)

// well defined, and specified to be 1099511627776u
#define TBYTE (UINT64_C(1024)*1024*1024*1024)


It also affects code via _Generic. The below could steer code to unsigned long, unsigned and unsigned long long.



(unsigned long) 123
UINT32_C(123)
UINT64_C(123)





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',
    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%2f53243019%2fwhat-is-the-point-of-the-u-intn-c-macros-in-stdint-h%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    2 Answers
    2






    active

    oldest

    votes








    2 Answers
    2






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes








    up vote
    2
    down vote













    The point of e.g. __UINT64_C(x) seems to be to attach the correct kind of suffix to x.



    In this way, the implementer of the C standard library header files are able to separate the numerical constants (which are the same on all platforms) from the suffixes (which depend on the integer size).



    For example, when building a 64-bit executable, the __UINT64_C(x) would evaluate to x ## UL, while when building a 32-bit executable, it would evaluate to x ## ULL.



    Edit: as @PSkocik points out, for signed integers this macro is not necessary. My guess is that it is still present as (1) the suffix is necessary for unsigned values and (2) the authors wanted to keep the code consistent for signed and unsigned constants.






    share|improve this answer























    • 9223372036854775807 doesn't need any suffix to be typed long on an LP64 platform. And if it doesn't fit long it'll be automatically long long (as per port70.net/~nsz/c/c11/n1570.html#6.4.4.1p5). And it must fit at least long long because long long is required to be present at least 64 bits wide.
      – PSkocik
      Nov 10 at 20:41















    up vote
    2
    down vote













    The point of e.g. __UINT64_C(x) seems to be to attach the correct kind of suffix to x.



    In this way, the implementer of the C standard library header files are able to separate the numerical constants (which are the same on all platforms) from the suffixes (which depend on the integer size).



    For example, when building a 64-bit executable, the __UINT64_C(x) would evaluate to x ## UL, while when building a 32-bit executable, it would evaluate to x ## ULL.



    Edit: as @PSkocik points out, for signed integers this macro is not necessary. My guess is that it is still present as (1) the suffix is necessary for unsigned values and (2) the authors wanted to keep the code consistent for signed and unsigned constants.






    share|improve this answer























    • 9223372036854775807 doesn't need any suffix to be typed long on an LP64 platform. And if it doesn't fit long it'll be automatically long long (as per port70.net/~nsz/c/c11/n1570.html#6.4.4.1p5). And it must fit at least long long because long long is required to be present at least 64 bits wide.
      – PSkocik
      Nov 10 at 20:41













    up vote
    2
    down vote










    up vote
    2
    down vote









    The point of e.g. __UINT64_C(x) seems to be to attach the correct kind of suffix to x.



    In this way, the implementer of the C standard library header files are able to separate the numerical constants (which are the same on all platforms) from the suffixes (which depend on the integer size).



    For example, when building a 64-bit executable, the __UINT64_C(x) would evaluate to x ## UL, while when building a 32-bit executable, it would evaluate to x ## ULL.



    Edit: as @PSkocik points out, for signed integers this macro is not necessary. My guess is that it is still present as (1) the suffix is necessary for unsigned values and (2) the authors wanted to keep the code consistent for signed and unsigned constants.






    share|improve this answer














    The point of e.g. __UINT64_C(x) seems to be to attach the correct kind of suffix to x.



    In this way, the implementer of the C standard library header files are able to separate the numerical constants (which are the same on all platforms) from the suffixes (which depend on the integer size).



    For example, when building a 64-bit executable, the __UINT64_C(x) would evaluate to x ## UL, while when building a 32-bit executable, it would evaluate to x ## ULL.



    Edit: as @PSkocik points out, for signed integers this macro is not necessary. My guess is that it is still present as (1) the suffix is necessary for unsigned values and (2) the authors wanted to keep the code consistent for signed and unsigned constants.







    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited Nov 10 at 20:47

























    answered Nov 10 at 20:30









    kfx

    4,82821535




    4,82821535












    • 9223372036854775807 doesn't need any suffix to be typed long on an LP64 platform. And if it doesn't fit long it'll be automatically long long (as per port70.net/~nsz/c/c11/n1570.html#6.4.4.1p5). And it must fit at least long long because long long is required to be present at least 64 bits wide.
      – PSkocik
      Nov 10 at 20:41


















    • 9223372036854775807 doesn't need any suffix to be typed long on an LP64 platform. And if it doesn't fit long it'll be automatically long long (as per port70.net/~nsz/c/c11/n1570.html#6.4.4.1p5). And it must fit at least long long because long long is required to be present at least 64 bits wide.
      – PSkocik
      Nov 10 at 20:41
















    9223372036854775807 doesn't need any suffix to be typed long on an LP64 platform. And if it doesn't fit long it'll be automatically long long (as per port70.net/~nsz/c/c11/n1570.html#6.4.4.1p5). And it must fit at least long long because long long is required to be present at least 64 bits wide.
    – PSkocik
    Nov 10 at 20:41




    9223372036854775807 doesn't need any suffix to be typed long on an LP64 platform. And if it doesn't fit long it'll be automatically long long (as per port70.net/~nsz/c/c11/n1570.html#6.4.4.1p5). And it must fit at least long long because long long is required to be present at least 64 bits wide.
    – PSkocik
    Nov 10 at 20:41












    up vote
    1
    down vote














    What is the point of the {U,}INTn_C macros in <stdint.h>?




    They insure a minimal type width and sign-ness for a constant.



    They "expand to an integer constant expression corresponding to the type (u)int_leastN_t."



    123 << 50                // likely int overflow (UB)
    INT32_C(123) << 50 // likely int overflow (UB)
    INT64_C(123) << 50 // well defined.
    INT32_C(123)*2000000000 // likely int overflow (UB)
    UINT32_C(123)*2000000000 // well defined - even though it may mathematically overflow


    Useful when defining computed constants.



    // well defined, but the wrong product when unsigned is 32-bit
    #define TBYTE (1024u*1024*1024*1024)

    // well defined, and specified to be 1099511627776u
    #define TBYTE (UINT64_C(1024)*1024*1024*1024)


    It also affects code via _Generic. The below could steer code to unsigned long, unsigned and unsigned long long.



    (unsigned long) 123
    UINT32_C(123)
    UINT64_C(123)





    share|improve this answer



























      up vote
      1
      down vote














      What is the point of the {U,}INTn_C macros in <stdint.h>?




      They insure a minimal type width and sign-ness for a constant.



      They "expand to an integer constant expression corresponding to the type (u)int_leastN_t."



      123 << 50                // likely int overflow (UB)
      INT32_C(123) << 50 // likely int overflow (UB)
      INT64_C(123) << 50 // well defined.
      INT32_C(123)*2000000000 // likely int overflow (UB)
      UINT32_C(123)*2000000000 // well defined - even though it may mathematically overflow


      Useful when defining computed constants.



      // well defined, but the wrong product when unsigned is 32-bit
      #define TBYTE (1024u*1024*1024*1024)

      // well defined, and specified to be 1099511627776u
      #define TBYTE (UINT64_C(1024)*1024*1024*1024)


      It also affects code via _Generic. The below could steer code to unsigned long, unsigned and unsigned long long.



      (unsigned long) 123
      UINT32_C(123)
      UINT64_C(123)





      share|improve this answer

























        up vote
        1
        down vote










        up vote
        1
        down vote










        What is the point of the {U,}INTn_C macros in <stdint.h>?




        They insure a minimal type width and sign-ness for a constant.



        They "expand to an integer constant expression corresponding to the type (u)int_leastN_t."



        123 << 50                // likely int overflow (UB)
        INT32_C(123) << 50 // likely int overflow (UB)
        INT64_C(123) << 50 // well defined.
        INT32_C(123)*2000000000 // likely int overflow (UB)
        UINT32_C(123)*2000000000 // well defined - even though it may mathematically overflow


        Useful when defining computed constants.



        // well defined, but the wrong product when unsigned is 32-bit
        #define TBYTE (1024u*1024*1024*1024)

        // well defined, and specified to be 1099511627776u
        #define TBYTE (UINT64_C(1024)*1024*1024*1024)


        It also affects code via _Generic. The below could steer code to unsigned long, unsigned and unsigned long long.



        (unsigned long) 123
        UINT32_C(123)
        UINT64_C(123)





        share|improve this answer















        What is the point of the {U,}INTn_C macros in <stdint.h>?




        They insure a minimal type width and sign-ness for a constant.



        They "expand to an integer constant expression corresponding to the type (u)int_leastN_t."



        123 << 50                // likely int overflow (UB)
        INT32_C(123) << 50 // likely int overflow (UB)
        INT64_C(123) << 50 // well defined.
        INT32_C(123)*2000000000 // likely int overflow (UB)
        UINT32_C(123)*2000000000 // well defined - even though it may mathematically overflow


        Useful when defining computed constants.



        // well defined, but the wrong product when unsigned is 32-bit
        #define TBYTE (1024u*1024*1024*1024)

        // well defined, and specified to be 1099511627776u
        #define TBYTE (UINT64_C(1024)*1024*1024*1024)


        It also affects code via _Generic. The below could steer code to unsigned long, unsigned and unsigned long long.



        (unsigned long) 123
        UINT32_C(123)
        UINT64_C(123)






        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited Nov 10 at 22:20

























        answered Nov 10 at 21:15









        chux

        78.4k869143




        78.4k869143






























             

            draft saved


            draft discarded



















































             


            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53243019%2fwhat-is-the-point-of-the-u-intn-c-macros-in-stdint-h%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

            Full-time equivalent

            さくらももこ

            13 indicted, 8 arrested in Calif. drug cartel investigation