7.20.4.1 Macros for minimum-width integer constants
... The macroUINTN_C(value)shall expand to an integer constant expression corresponding to the typeuint_leastN_t. For example, ifuint_least64_tis a name for the typeunsigned long long int, thenUINT64_C(0x123) might expand to the integer constant0x123ULL. C11dr §7.20.4.1 1
The type of UINTN_C() and friends are not as expected. See "Expected" comments in code output.
A) Is my compiler implementation wrong and the constant type should be uint_leastN_t?
or
B) Should the type of constant from UINTN_C(value) be the minimum of uint_leastN_t, int, unsigned and type needed to encode the value?
or
C) something else?
I had expected that the type of the constants to correspond to uint_leastN_t, but it appears to not be so under 2 conditions:
**1 If the macro corresponding type is below int/unsigned, the constant is int/unsigned
**2 If the value exceeds the range of the 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;
}
Output
2 unsigned short
4 unsigned
8 unsigned long long
2 unsigned short
4 int // Expected 2 unsigned short, see **1
4 int // Expected 2 unsigned short, see **1
4 int // Expected 2 unsigned short, see **2
4 unsigned
8 unsigned long long // Expected 4 unsigned, see **2
I am using (GNU C11 (GCC) version 5.4.0)
In forming this post, I am leaning toward B, yet I am looking for your rational for confirmation -one way of the other. If B is so, a disappointing part is that UINTN_C() could result in a signed type.
I suppose that is what the "minimum-width" part is about.