Печать unsigned long long int Тип значения Возвращает странные результаты
У меня есть проблема при использовании функции 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
from 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
для печати двух нулей
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)
Почему он ведет себя так? Не могли бы вы объяснить это мне?
Ответы
Ответ 1
Это неправильно:
printf("unsigned long long int: \n%llu to %llu \n\n", 0, ULONG_MAX);
Вы используете спецификатор формата unsigned long long
, но вы передаете значение int
и unsigned long
. Правила продвижения означают, что вы можете быть sloppy для всего int
-размер или меньше, что не относится к 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
. Также можно передать тип unsigned в спецификатор подписанного формата или наоборот, если переданное значение может быть представлено с использованием типа, указанного спецификатором формата.
Итак, вы должны быть осторожны с long
и long long
, но вы можете быть неаккуратными с int
, short
и char
.
Большинство компиляторов имеют настройки, чтобы заставить их предупреждать вас об этом типе ошибок, поскольку его можно легко обнаружить во время компиляции; GCC и Clang имеют -Wformat
, что приводит к следующим предупреждениям:
test.c:5: warning: format ‘%llu’ expects type ‘long long unsigned int’, but argument 2 has type ‘int’
test.c:5: warning: format ‘%llu’ expects type ‘long long unsigned int’, but argument 3 has type ‘long unsigned int’
Ответ 2
Вы не проходите 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);
Ответ 3
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()
соответствуют спецификаторам формата.
Ответ 4
long long int - это тип из стандарта C99, MSVC не поддерживает это. Возьмите компилятор с поддержкой C99 (например, MinGW для Windows), и он будет работать.