У меня проблема при использовании printf
для печати значений типа unsigned long long int
Я понятия не имею, что случилось. Я использую Dev-Cpp 4.9.9.2 и Visual Studio 2010 Professional (я знаю, что это не компилятор C, но в любом случае хотел попробовать) на Windows 7 Professional 64-bit. Для отображения я использовал модификатор %llu
(в соответствии с тем, как вы печатаете unsigned long long int (спецификатор формата для unsigned long long int)? ), Но я также попытался I64d без эффекта …
Во-первых, я просто хотел напечатать минимальное и максимальное значение unsigned long long int
(используя ULONG_MAX
из limits.h
)
printf("unsigned long long int: \n%llu to %llu \n\n", 0, ULONG_MAX);
Возвращает:
unsigned long long int: 18446744069414584320 – 1580552164021 (Dev-Cpp)
unsigned long long int: 18446744069414584320 – 0 (Visual Studio)
Затем я попытался использовать printf
для печати двух нhive
printf("unsigned long long int: \n%llu to %llu \n\n", 0, 0);
Возвращает:
unsigned long long int: от 0 до 1580552164021 (Dev-Cpp)
unsigned long long int: от 0 до 0 (Visual Studio)
Также попробовали два значения ULONG_MAX
printf("unsigned long long int: \n%llu to %llu \n\n", ULONG_MAX, ULONG_MAX);
Возвращает:
unsigned long long int: 18446744073709551615 до 1580552164021 (Dev-Cpp)
unsigned long long int: 18446744073709551615 – 0 (Visual Studio)
Почему он ведет себя так? Не могли бы вы объяснить мне это?
Это не верно:
printf("unsigned long long int: \n%llu to %llu \n\n", 0, ULONG_MAX);
Вы используете unsigned long long
specifier, но вы передаете значение int
и unsigned long
. Правила продвижения означают, что вы можете быть неаккуратным для всего, что было сделано или меньше, что не относится к long long
периоду.
Используйте броски:
printf("unsigned long long int: \n%llu to %llu \n\n", 0ULL, (unsigned long long) ULONG_MAX);
Объяснение: При передаче аргументов printf
любому типу, который может вписываться в int
, присваивается значение int
, а затем любой тип, который может вписываться в unsigned int
, передается в unsigned int
. Также можно передать беззнаковый тип в спецификатор подписанного формата или наоборот, если переданное значение может быть представлено с использованием типа, указанного спецификатором формата.
Поэтому вы должны быть осторожны с long
и long long
, но вы можете быть неаккуратными с int
, short
и char
.
У большинства компиляторов есть настройки, чтобы заставить их предупреждать вас об этом типе ошибок, поскольку его можно легко обнаружить во время компиляции; GCC и Clang имеют -Wformat
что приводит к следующим предупреждениям:
test.c: 5: warning: format '% llu' ожидает тип long long unsigned int, но аргумент 2 имеет тип 'int' test.c: 5: warning: format '% llu' ожидает тип long long unsigned int, но аргумент 3 имеет тип long long unsigned int,
Вы не пропустите unsigned long longs
. Вы передаете int
(0) и unsigned long
(ULONG_MAX). Вы должны передать printf()
именно то, что вы обещаете передать в строке формата.
Попробуйте это вместо этого:
printf("unsigned long long int: \n%llu to %llu \n\n", 0ULL, (unsigned long long)ULONG_MAX);
ULONG_MAX
относится к unsigned long
а не к unsigned long long
. Для последнего используйте ULLONG_MAX
(обратите внимание на дополнительный L
).
Вам нужно изменить вызовы printf()
следующим образом:
printf("unsigned long long int: \n%llu to %llu \n\n", 0ULL, ULLONG_MAX); printf("unsigned long long int: \n%llu to %llu \n\n", ULLONG_MAX, ULLONG_MAX);
Это гарантирует соответствие аргументов printf()
спецификаторам формата.
long long int – это тип от стандарта C99, MSVC этого не поддерживает. Возьмите компилятор с поддержкой C99 (например, MinGW для Windows), и он будет работать.