Неожиданные типы из UINT32 C, UINTN C
7.20.4.1 макросы для целочисленных констант минимальной ширины
... МакросUINTN_C(value)
расширяется до целочисленного постоянного выражения, соответствующего типуuint_leastN_t
. Например, еслиuint_least64_t
- это имя типаunsigned long long int
, потомUINT64_C(0x123
) может расширяться до целочисленной константы0x123ULL
. C11dr §7.20.4.1 1
типа UINTN_C()
и друзья не так, как ожидалось. См." ожидаемые " комментарии в выводе кода.
A) Является ли моя реализация компилятора неправильной, и тип константы должен быть uint_leastN_t
?
или
B) должен ли тип константы от UINTN_C(value)
быть минимум uint_leastN_t
, int
, unsigned
и тип, необходимый для кодирования значения?
или
В) что-то еще?
я ожидал, что тип констант будет соответствовать uint_leastN_t
, но, похоже, это не так при 2 условиях:
* * 1, если соответствующий тип макроса ниже int/unsigned
, в константа int/unsigned
**2 Если значение превышает диапазон uint_leastN_t
, тогда тип становится более широкой константой типа.
§6.4.4.1 " тип целочисленной константы является первым из соответствующего списка, в котором может быть представлено ее значение ... (далее следует длинный список).
#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 %sn", sizeof(u16), type_of(u16));
printf("%zu %sn", sizeof(u32), type_of(u32));
printf("%zu %sn", sizeof(u64), type_of(u64));
puts("");
printf("%zu %sn", sizeof((uint_least16_t) UINT16_C(0)), type_of((uint_least16_t) UINT16_C(0)));
printf("%zu %sn", sizeof UINT16_C(0), type_of(UINT16_C(0)));
printf("%zu %sn", sizeof UINT16_C(0x1234), type_of(UINT16_C(0x1234)));
printf("%zu %sn", sizeof UINT16_C(0x12345), type_of(UINT16_C(0x12345)));
printf("%zu %sn", sizeof UINT32_C(0x12345678), type_of(UINT32_C(0x12345678)));
printf("%zu %sn", 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;
}
выход
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
я использую (GNU C11 (GCC) версия 5.4.0)
при формировании этого поста я склоняюсь по направлению к Б, и все же я ищу ваше рациональное подтверждение-один путь другого. Если B так, разочаровывающая часть-это UINTN_C()
может привести к подпись тип.
я полагаю, что это то, о чем идет речь в части" минимальная ширина".
2 ответов
это описано в Родительском подразделе 7.20.4.
в той части, которую вы процитировали:
макрос
UINTN_C(value)
расширяется до целочисленного постоянного выражения >, соответствующего типуuint_leastN_t
.
Он говорит:"соответствующую", не то, что расширение на самом деле of этого типа. Смысл "соответствующую" объясняется в 7.20.4p3:
каждый вызов один из этих макросов должен расширяться до целого числа постоянное выражение, подходящее для использования в
#if
директивы препроцессора. Тип выражения должен иметь тот же тип, что и выражение соответствующего типа, преобразованное в соответствии с целочисленные акции. Значение выражения должно быть аргумент.
поскольку макросы предназначены для использования в элементе
на хосте с 16 бит short
и 32-разрядные целые числа unsigned short
цифры повышаются до int
. Таким образом, эти макросы определяются как:
#define INT16_C(x) (x)
#define UINT16_C(x) (x)
без суффикса " U " для unsigned short
если int может представить все значения исходного типа (Как ограничено по ширине, для битового поля), значение преобразуется в int;
эти макросы расширяются только до соответствующих констант (или целочисленных литералов, использующих более распространенные язык), и не создавайте никаких объектов, и должны использоваться в #if. Так что никаких гипсов не допускается. Макросы также не выполняют никаких проверок диапазона.
int16_t x0 = 123;
uint16_t x1 = 123; // no sign suffix needed
int32_t x2 = 2147483647;
uint32_t x3 = 2147583647U; //sign suffix theoreticaly needed as int and unsigned int have the same rank
int64_t x4 = 9223372036854775807LL;
uint64_t x5 = 9237372036854775807ULL; //same as above