#include <stdio.h>
int main() {
unsigned long long int num = 285212672; //FYI: fits in 29 bits
int normalInt = 5;
printf("My number is %d bytes wide and its value is %ul. A normal number is %d.\n", sizeof(num), num, normalInt);
return 0;
}
Выход:
My number is 8 bytes wide and its value is 285212672l. A normal number is 0.
Я предполагаю, что этот неожиданный результат связан с печатью unsigned long long int. Как вам printf() и unsigned long long int?
Я бы предложил использовать stdint.h и указать количество бит в вашей переменной. Мы все еще находимся в периоде перехода между 32- и 64-битными архитектурами, и «unsigned long long int» не означает одно и то же для обеих.
Я только что скомпилировал ваш код (с% llu) с помощью gcc, и результат был правильным. Вы передаете какие-либо параметры компилятору?
Обратите внимание, что новая библиотека samsung bada, похоже, не поддерживает "% lld": developer.bada.com/forum/…





Используйте модификатор ll (el-el) long-long с преобразованием u (без знака). (Работает в Windows, GNU).
printf("%llu", 285212672);
Или, если быть точным, это для GNU libc и не работает со средой выполнения Microsoft C.
Это не Linux / UNIX, модификатор длины "ll" был добавлен к стандарту C в C99, если он не работает в "Microsoft C", то это потому, что они не соответствуют стандартам.
Работает в Turbo C++ в Windows
У меня работает в VS2008. Более того, насколько я помню, компилятор MS C (когда он настроен для компиляции прямого C) должен быть совместим с C90 по дизайну; C99 представил некоторые вещи, которые понравились не всем.
Здесь следует иметь в виду, что если вы передаете несколько аргументов long long в printf и используете неправильный формат для одного из них, скажем %d вместо %lld, тогда даже аргументы, напечатанные после, неправильный, могут быть полностью отключены (или даже вызвать сбой printf). По сути, переменные аргументы передаются в printf без какой-либо информации о типе, поэтому, если строка формата неверна, результат непредсказуем.
Слышал, как Херб Саттер сказал в интервью, что клиенты Microsoft не просят C99, поэтому их компилятор на чистом C был заморожен на C90. Это применимо, если вы компилируете как C. Если вы компилируете как C++, как другие отмечали выше, все будет в порядке.
Я не понимаю, почему такой ответ еще не был принят.
все меняется на 64-битной машине
Использование компилятора Cygwin, который выполняет кросс-компиляцию в x86_64 (x86_64-w64-mingw32-g ++)% lx с длинным длинным беззнаковым int, дает ошибку о том, что формат и тип не совпадают, и использование% llx с той же переменной и тот же компилятор выдает ошибку% llx - неизвестный формат. И на самом деле переменная - это pthread_t. Так что он не «работает в Windows / GNU», и проблема не в том, что это компилятор Microsoft.
Для вывода в шестнадцатеричном формате длинное число без знака будет напечатано с% I64x. Практически переносимый способ - привести число к intmax_t и использовать PRIXMAX. А чтобы использовать PRIXMAX или что-то подобное с C++ в компиляторе GNU, вам нужно #define __STDC_FORMAT_MACROS. И в условиях, которые я описываю, определение PRIXMAX, которое я получаю, кажется неправильным, и мне нужно принудительно установить% I64X, который работает.
Почему не ull вместо llu?
Нестандартные вещи всегда странные :)
на длинную длинную порцию
под GNU это L, ll или q
а под окнами я считаю, что это только ll
Ну, один из способов - скомпилировать его как x64 с VS2008
Это работает, как и следовало ожидать:
int normalInt = 5;
unsigned long long int num=285212672;
printf(
"My number is %d bytes wide and its value is %ul.
A normal number is %d \n",
sizeof(num),
num,
normalInt);
Для 32-битного кода нам нужно использовать правильный описатель формата __int64% I64u. Так и становится.
int normalInt = 5;
unsigned __int64 num=285212672;
printf(
"My number is %d bytes wide and its value is %I64u.
A normal number is %d",
sizeof(num),
num, normalInt);
Этот код работает как для 32-битного, так и для 64-битного компилятора VS.
Попробуйте использовать реальное 64-битное число вместо «285212672», и я не верю, что первый пример работает правильно, скомпилированный для какой-либо цели.
Вы можете попробовать использовать библиотеку inttypes.h, которая дает вам такие типы, как
int32_t, int64_t, uint64_t и т. д.
Затем вы можете использовать его макросы, такие как:
uint64_t x;
uint32_t y;
printf("x: %"PRId64", y: %"PRId32"\n", x, y);
Это «гарантированно» не доставит вам тех же проблем, что и long, unsigned long long и т. д., Поскольку вам не нужно угадывать, сколько бит находится в каждом типе данных.
где эти макросы PRId64, PRId32 определены?
@happy_marmoset: они определены в inttypes.h
Я думаю, вам нужны PRIu64 и PRIu32 для целых чисел без знака.
Стандарт inttypes.h? Разве это не было бы stdint.h?
Ints есть в обоих, inttypes также содержат bools, которые можно найти в stdbool.h
Обратите внимание, что этими типами точной ширины являются необязательный, поскольку существуют архитектуры, в которых целочисленные типы нет имеют такую точную ширину. Только типы leastX и fastX (которые на самом деле могут быть шире, чем указано) являются обязательными.
Ошибка в кодовых блоках: error: unknown type name 'uint64_t'; did you mean 'wint_t'?|
@john: нет, uint64_t. Я считать, что это несколько нестандартное расширение, поэтому разные компиляторы или среды могут иметь разные имена.
Это потому, что% llu не работает должным образом под Windows, а% d не может обрабатывать 64-битные целые числа. Я предлагаю вместо этого использовать PRIu64, и вы также обнаружите, что он переносится на Linux.
Попробуйте вместо этого:
#include <stdio.h>
#include <inttypes.h>
int main() {
unsigned long long int num = 285212672; //FYI: fits in 29 bits
int normalInt = 5;
/* NOTE: PRIu64 is a preprocessor macro and thus should go outside the quoted string. */
printf("My number is %d bytes wide and its value is %" PRIu64 ". A normal number is %d.\n", sizeof(num), num, normalInt);
return 0;
}
Выход
My number is 8 bytes wide and its value is 285212672. A normal number is 5.
+1 за ссылку на PRIu64, которого я никогда не видел, но он не кажется переносимым на 64-битный Linux (по крайней мере), потому что PRIu64 расширяется до lu вместо llu.
И почему это должно быть плохо? Long - это 64-битное значение в 64-битном Linux, как и во всех других ОС, кроме Windows.
@BDatRivenhill Linux / Unix использует LP64, в котором long составляет 64 бита
однако, чтобы сделать его более портативным, используйте вместо него int64_t, потому что вполне могут быть некоторые реализации с long long больше, чем long
это должно наверх! - одно небольшое обновление: ошибка: неверный суффикс в литерале; C++ 11 требует пробела между литералом и идентификатором [-Wreserved-user-defined-literal]
В Linux это %llu, а в Windows - %I64u.
Хотя я обнаружил, что это не работает в Windows 2000, похоже, там есть ошибка!
с Windows (или, по крайней мере, с компилятором Microsoft C для Windows) есть также% I64d,% I32u и% I32d
При чем здесь Windows 2000? Библиотека C - это та, которая обрабатывает printf.
То, что я заметил. Я написал приложение, которое использовало эту конструкцию, и оно отлично работало на WinXP, но выплевывало мусор на Win2k. Может быть, это как-то связано с системным вызовом, который библиотека C делает к ядру, может быть, это как-то связано с Unicode, кто знает. Я помню, что приходилось обходить это с помощью _i64tot () или что-то в этом роде.
Похоже, MS снова использует свою "свободу инноваций" ... ;-)
Проблема Win2k / Win9x, вероятно, связана с тем, что тип данных unsigned long long был относительно новым (в то время со стандартом C99), но компиляторы C (включая MinGW / GCC) использовали старую среду выполнения Microsoft C, которая поддерживала только спецификацию C89. У меня есть доступ только к действительно старым и достаточно свежим документам Windows API. Так что сложно сказать, когда именно была прекращена поддержка I64u. Но это похоже на эпоху XP.
Для long long (или __int64) с использованием MSVS вы должны использовать% I64d:
__int64 a;
time_t b;
...
fprintf(outFile,"%I64d,%I64d\n",a,b); //I is capital i
Скомпилируйте его как x64 с VS2005:
%llu works well.
%d -> для int
%u -> для unsigned int
%ld -> для long int или long
%lu -> для unsigned long int или long unsigned int или unsigned long
%lld -> для long long int или long long
%llu -> для unsigned long long int или unsigned long long
Шестнадцатеричный:
printf("64bit: %llp", 0xffffffffffffffff);
Выход:
64bit: FFFFFFFFFFFFFFFF
Очень хорошо! Мне было интересно, как я могу получить его в шестнадцатеричном представлении
Но почти все компиляторы C++ и C выдают предупреждение: предупреждение: использование модификатора длины 'll' с символом типа 'p' [-Wformat =]
@AnttiHaapala Вы говорите, что этот ответ полностью нарушен двойным неопределенным поведением, вы можете уточнить или мне просто удалить его? Или оставить это как хороший плохой пример?
UB1: все указатели имеют одинаковый размер, sizeof (char *) == sizeof (long long *), поэтому модификатор размера для% p бесполезен. UB2: 0xff.fff - это тип int, а формат% p ожидает указатель
В дополнение к тому, что люди писали много лет назад:
main.c:30:3: warning: unknown conversion type character 'l' in format [-Wformat=]
printf("%llu\n", k);
Тогда ваша версия mingw по умолчанию не c99. Добавьте этот флаг компилятора: -std=c99.
Очевидно, никто не придумал мультиплатформенного * решения для более десяти лет с [] 2008 года, поэтому я добавлю свое ?. Пожалуйста, проголосуйте за. (Шучу. Меня это не волнует.)
lltoa()Как пользоваться:
#include <stdlib.h> /* lltoa() */
// ...
char dummy[255];
printf("Over 4 bytes: %s\n", lltoa(5555555555, dummy, 10));
printf("Another one: %s\n", lltoa(15555555555, dummy, 10));
Пример ОП:
#include <stdio.h>
#include <stdlib.h> /* lltoa() */
int main() {
unsigned long long int num = 285212672; // fits in 29 bits
char dummy[255];
int normalInt = 5;
printf("My number is %d bytes wide and its value is %s. "
"A normal number is %d.\n",
sizeof(num), lltoa(num, dummy, 10), normalInt);
return 0;
}
В отличие от строки формата печати %lld, этот у меня работает под 32-битным GCC в Windows.
*) Что ж, почти мультиплатформенный. В MSVC вам явно нужен _ui64toa() вместо lltoa().
У меня нет lltoa.
твой смайлик повлиял на мои кимодзи.
How do you format an
unsigned long long intusingprintf?
Начиная с C99, перед спецификаторами преобразования "ll" используется o,u,x,X (многоточие).
Помимо вариантов с основанием 10 во многих ответах есть варианты с основанием 16 и основанием 8:
Варианты включают
unsigned long long num = 285212672;
printf("Base 10: %llu\n", num);
num += 0xFFF; // For more interesting hex/octal output.
printf("Base 16: %llX\n", num); // Use uppercase A-F
printf("Base 16: %llx\n", num); // Use lowercase a-f
printf("Base 8: %llo\n", num);
puts("or 0x,0X prefix");
printf("Base 16: %#llX %#llX\n", num, 0ull); // When non-zero, print leading 0x
printf("Base 16: %#llx %#llx\n", num, 0ull);
printf("Base 16: 0x%llX\n", num); // My hex fave: lower case prefix, with A-F
Выход
Base 10: 285212672
Base 16: 11000FFF
Base 16: 11000fff
Base 8: 2100007777
or 0x,0X prefix
Base 16: 0X11000FFF 0
Base 16: 0x11000fff 0
Base 16: 0x11000FFF
+ l: "% llu" меня удивил. Я использовал "% ull" и получил предупреждение, что я предоставил int.
@Rainning "%ull" печатает unsigned, а затем "ll".
См. Также stackoverflow.com/questions/5140871/sprintf-for-unsigned-int 64