7.20.4.1 Macros for integer constants of minimum width
... The macro UINTN_C(value) will expand to an integer constant expression corresponding to the type uint_leastN_t . For example, if uint_least64_t is the name for the type unsigned long long int , then UINT64_C(0x123 ) can expand to the integer constant 0x123ULL . C11dr Β§7.20.4.1 1
Type UINTN_C() and friends are not as expected. See "Expected" comments in the code output.
A) Is my compiler implementation wrong and should the constant type be uint_leastN_t ?
or
B) Should the constant type from UINTN_C(value) be the minimum value of uint_leastN_t , int , unsigned and the type needed to encode the value?
or
C) something else?
I was expecting the constant type to match uint_leastN_t , but it seems this is not the case under two conditions:
** 1 If the corresponding macro type is below int/unsigned , the constant is int/unsigned
** 2 If the value exceeds the range uint_leastN_t , then the type becomes a wider type constant.
Β§6.4.4.1 "The type of an integer constant is the first of the corresponding list in which its value can be represented ... (long list follows).
#include <limits.h> #include <stdio.h> #define type_of(X) _Generic((X), \ unsigned long long: "unsigned long long", \ unsigned long: "unsigned long", \ unsigned: "unsigned", \ int: "int", \ unsigned short: "unsigned short", \ default: "?" \ ) int main() { uint_least16_t u16 = 0; uint_least32_t u32 = 0; uint_least64_t u64 = 0; printf("%zu %s\n", sizeof(u16), type_of(u16)); printf("%zu %s\n", sizeof(u32), type_of(u32)); printf("%zu %s\n", sizeof(u64), type_of(u64)); puts(""); printf("%zu %s\n", sizeof((uint_least16_t) UINT16_C(0)), type_of((uint_least16_t) UINT16_C(0))); printf("%zu %s\n", sizeof UINT16_C(0), type_of(UINT16_C(0))); printf("%zu %s\n", sizeof UINT16_C(0x1234), type_of(UINT16_C(0x1234))); printf("%zu %s\n", sizeof UINT16_C(0x12345), type_of(UINT16_C(0x12345))); printf("%zu %s\n", sizeof UINT32_C(0x12345678), type_of(UINT32_C(0x12345678))); printf("%zu %s\n", sizeof UINT32_C(0x123456789), type_of(UINT32_C(0x123456789))); return 0; //round_frac_test(-2.05446162500000000e+06, 205); round_frac_test(fp_rand(), 6); round_frac_tests(10000); puts("Done"); return 0; }
Exit
2 unsigned short 4 unsigned 8 unsigned long long 2 unsigned short 4 int
I am using (GNU C11 (GCC) version 5.4.0)
By creating this post, I lean toward B, but I'm looking for your reasonable confirmation to confirm a different path. If B is so, the disappointing part is that UINTN_C() can lead to a signed type.
I believe that this is what we are talking about the part of the minimum width.