Как вы форматируете unsigned long long int, используя printf?

379
#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?

andrewrk
источник
2
Я только что скомпилировал ваш код (с% llu) с помощью gcc, и вывод был правильным. Вы передаете какие-либо параметры компилятору?
Хуан
2
Обратите внимание, что newlib от samsung bada, похоже, не поддерживает "% lld": developer.bada.com/forum/…
RzR 7.10.10
Я бы предложил использовать stdint.h и точно указать количество бит в вашей переменной. Мы все еще находимся в переходном периоде между 32- и 64-разрядными архитектурами, и «unsigned long long int» не означает одно и то же для обоих.
BD в Ривенхилле

Ответы:

483

Используйте модификатор long (long) ll (el-el) с преобразованием u (без знака). (Работает в windows, GNU).

printf("%llu", 285212672);
Джон Дауни
источник
11
Или, если быть точным, это для GNU libc, и не работает с Microsoft C времени выполнения.
Марк Бейкер
168
Это не Linux / UNIX, модификатор длины ll будет добавлен в Standard C в C99, если он не работает в «Microsoft C», то это потому, что они не соответствуют стандартам.
Роберт Гэмбл
12
У меня работает в VS2008. Более того, насколько я помню, компилятор MS C (когда он настроен на прямую компиляцию C) должен быть совместим с C90 по своему дизайну; C99 представил некоторые вещи, которые понравились не всем.
ン 20: パ ー フ ァ ミ コ ン
6
Здесь нужно помнить одну вещь: если вы передаете несколько long longаргументов printfи используете неправильный формат для одного из них, скажем, %dвместо %lld, то даже аргументы, напечатанные после неправильного, могут быть полностью отключены (или даже могут привести printfк сбою). ). По сути, переменные аргументы передаются в printf без какой-либо информации о типе, поэтому, если строка формата неверна, результат непредсказуем.
дмитрий
1
Херд Саттер сказал в интервью, что клиенты Microsoft не просят C99, поэтому их чистый компилятор C был заморожен на C90. Это применимо, если вы компилируете как C. Если вы компилируете как C ++, как уже отмечали другие, у вас все будет хорошо.
АХКОКС
90

Вы можете попробовать использовать библиотеку 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
4
@happy_marmoset: они определены вinttypes.h
Натан Феллман
4
Я думаю, что вам нужно PRIu64и PRIu32для целых чисел без знака.
Лассе Климанн
1
Это inttypes.hстандарт? Не будет ли это stdint.h?
MD XF
2
Обратите внимание, что эти типы точной ширины являются необязательными , поскольку существуют архитектуры, которые не имеют целочисленных типов с такой точной шириной. Только leastXи fastXтипы (которые на самом деле может быть шире , чем указано иное) являются обязательными.
DevSolar
78

%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

Шивам Чаухан
источник
Существует ли спецификатор формата, например количество отображаемых цифр, выравнивание по левому или правому краю для% lld или% llu?
Асам Падех
40

Чтобы долго (или __int64) использовать MSVS, вы должны использовать% I64d:

__int64 a;
time_t b;
...
fprintf(outFile,"%I64d,%I64d\n",a,b);    //I is capital i

источник
37

Это связано с тем, что% 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».
BD в Ривенхилле
8
И почему это было бы плохо? Long - это 64-битное значение в 64-битной Linux, как и в любой другой ОС, кроме Windows.
Звон
@BDatRivenhill Linux / Unix использует LP64, длина которого составляет 64 бита
phuclv
1
однако, чтобы сделать его более переносимым, используйте int64_tвместо этого, потому что вполне могут быть некоторые реализации с длинным длинным большим, чем длинный
phuclv
это должно наверх! - одно небольшое обновление: ошибка: неверный суффикс на литерале; C ++ 11 требует пробела между литералом и идентификатором [-Wreserved-user-define-literal]
tofutim
14

В Linux это есть, %lluа в Windows это%I64u

Хотя я обнаружил, что это не работает в Windows 2000, там, похоже, есть ошибка!

Адам Пирс
источник
с Windows (или, по крайней мере, с компилятором Microsoft C для Windows) есть также% I64d,% I32u и% I32d
JustJeff
1
Какое это имеет отношение к Windows 2000? Библиотека C - это та, которая обрабатывает printf.
CMircea
1
Как раз то, что я заметил. Я написал приложение, которое использовало эту конструкцию, и оно отлично работало на WinXP, но плюнуло на Win2k. Может быть, это как-то связано с системным вызовом, который библиотека C делает с ядром, может быть, это как-то связано с Unicode, кто знает. Я помню, что мне приходилось обходить его, используя _i64tot () или что-то в этом роде.
Адам Пирс
7
Похоже, MS снова использует свою «свободу инноваций» ... ;-)
Dronz
Вероятно, проблема Win2k / Win9x связана с тем, что unsigned long longтип данных является относительно новым (в то время, со стандартом C99), но компиляторами C (включая MinGW / GCC), использующими старую среду выполнения Microsoft C, которая поддерживала только спецификацию C89. У меня есть доступ только к действительно старым и достаточно свежим документам по Windows API. Так что сложно сказать, когда именно I64uбыла добавлена ​​поддержка. Но это похоже на эпоху XP.
veganaiZe
8

Скомпилируйте его как x64 с VS2005:

% llu работает хорошо.

Сэнди
источник
3

В дополнение к тому, что люди написали много лет назад:

  • Вы можете получить эту ошибку в gcc / mingw:

main.c:30:3: warning: unknown conversion type character 'l' in format [-Wformat=]

printf("%llu\n", k);

Тогда ваша версия mingw не по умолчанию c99. Добавьте этот флаг компилятора: -std=c99.

Бернд Элькеманн
источник
3

Очевидно, никто не придумал мультиплатформенное * решение в течение более десяти лет с [2008 года], поэтому я добавлю свое mine. Плз upvote. (Шучу. Мне все равно.)

Решение: 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().

7vujy0f0hy
источник
1
Я не имею lltoa.
Антти Хаапала
1

Нестандартные вещи всегда странные :)

для длинной длинной части под GNU это L, llилиq

и под окнами я считаю, что это llтолько

Sparkes
источник
1

Hex:

printf("64bit: %llp", 0xffffffffffffffff);

Вывод:

64bit: FFFFFFFFFFFFFFFF
lama12345
источник
Очень хорошо! мне было интересно, как я могу получить его в шестнадцатеричном представлении
0xAK
Но почти все компиляторы C ++ и C выдают предупреждение: warning: используйте модификатор длины 'll' с символом типа 'p' [-Wformat =]
Seshadri R
2
этот совершенно неверный ответ имеет двусмысленное поведение и даже не начинает отвечать на вопрос .
Антти Хаапала
@AnttiHaapala Вы говорите, что этот ответ полностью нарушен двусмысленным поведением, можете ли вы уточнить или я просто удалил его? Или оставить это как хороший плохой пример?
lama12345
0

Ну, один из способов - это скомпилировать его как 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.

vzczc
источник
Попробуйте использовать действительное 64-разрядное число вместо «285212672», и я не верю, что первый пример работает правильно, скомпилированный для любой цели.
Дьяста