Як відформатувати неподписаний довгий довгий 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?


2
Я щойно скомпілював ваш код (з% llu) з gcc, і вихід був правильним. Чи передаєте якісь варіанти компілятору?
Хуан

2
Зауважте, що newlib для Samsung bada, здається, не підтримує "% lld": developer.bada.com/forum/…
RzR


Я б запропонував використовувати stdint.h та бути чітким щодо кількості бітів у вашій змінній. Ми все ще перебуваємо в перехідному періоді між 32 та 64-бітовою архітектурою, і "неподписаний довгий довгий int" не означає те ж саме для обох.
BD у Rivenhill

Відповіді:


483

Використовуйте модифікатор ll (el-el) на довгий час із перетворенням u (непідписаний). (Працює у вікнах, GNU).

printf("%llu", 285212672);

11
Або якщо бути точним, це GNU libc, і він не працює з Microsoft C часу виконання.
Марк Бейкер

168
Це не Linux / UNIX, модифікатор довжини "ll" додано до стандарту C в C99, якщо він не працює в "Microsoft C", це тому, що вони не відповідають стандартам.
Роберт Гембл

12
Для мене працює у VS2008. Більше того, наскільки я пам’ятаю, компілятор MS C (коли він налаштований на компіляцію прямого C) повинен бути C90 сумісним за конструкцією; C99 представив деякі речі, які не всім подобалися.
ス ー パ ー フ ァ ミ ン

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 у Rivenhill

8
І чому це було б погано? Довге - це 64-бітове значення для 64-бітного Linux, як і для всіх інших ОС, крім Windows.
Дзвінка

@BDatRivenhill Linux / Unix використовує LP64, у якому довгий 64 біт
phuclv

1
однак, щоб зробити його більш портативним, використовуйте int64_tнатомість, тому що цілком можуть бути деякі реалізації з довгими,
довшими,

це повинно до вершини! - одне невелике оновлення: помилка: недійсний суфікс на буквальному; C ++ 11 вимагає пробілу між літералом та ідентифікатором [-зазначений користувачем-
літералом

14

В Linux це є, %lluа в Windows є%I64u

Хоча я виявив, що він не працює в Windows 2000, там, здається, є помилка!


з Windows (або, принаймні, з компілятором microsoft C для Windows) є також% I64d,% I32u та% I32d
JustJeff

1
Що це стосується Windows 2000? Бібліотека С - це та, яка обробляє printf.
CMircea

1
Тільки те, що я спостерігав. Я написав додаток, який використовував цю конструкцію, і вона чудово працювала на WinXP, але розсипала сміття на Win2k. Можливо, це щось стосується системного виклику, який бібліотека C робить до ядра, можливо, це щось стосується Unicode, хто знає. Я пам’ятаю, що мені довелося обійти це за допомогою _i64tot () чи чогось подібного.
Адам Пірс

7
Здається, що МС знову
реалізує

Випуск Win2k / Win9x, ймовірно, пов'язаний з тим, що unsigned long longтип даних був відносно новим (на той час, зі стандартом C99), але компілятори C (включаючи MinGW / GCC), використовуючи старий час виконання Microsoft C, який підтримував лише специфікацію C89. У мене є доступ до дійсно старих і досить останніх документів Windows API. Тому важко точно сказати, коли I64uпідтримка потрапила. Але це звучить як епоха XP.
veganaiZe


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 року, тому я додаю шахту 😛. Plz 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().


1
Я не маю lltoa.
Антті

1

Нестандартні речі завжди дивні :)

для довгої довгої частини в GNU це L, llабоq

а під вікнами я вірю, що це llтільки


1

Hex:

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

Вихід:

64bit: FFFFFFFFFFFFFFFF

Дуже хороший! Мені було цікаво, як я міг отримати це в шестигранному поданні
0xAK

Але майже всі компілятори C ++ і C дають попередження: попередження: використання модифікатора довжини '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.


Спробуйте дійсне 64-бітове число замість "285212672", і я не вірю, що перший приклад працює правильно, складений до будь-якої цілі.
діаста
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.