Come si formatta un int long long senza segno usando 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;
}

Produzione:

My number is 8 bytes wide and its value is 285212672l. A normal number is 0.

Presumo che questo risultato inaspettato sia dovuto alla stampa di unsigned long long int. Come si fa printf()un unsigned long long int?


2
Ho appena compilato il tuo codice (con% llu) con gcc e l'output era quello corretto. Stai passando qualche opzione al compilatore?
— Juan,

2
Si noti che il newlib di samsung bada sembra non supportare "% lld": developer.bada.com/forum/…
— RzR


Suggerirei di usare stdint.h e di essere esplicito sul numero di bit nella tua variabile. Siamo ancora in un periodo di transizione tra architetture a 32 e 64 bit e "unsigned long long int" non significa la stessa cosa per entrambi.
— BD a Rivenhill,

Risposte:


483

Usa il modificatore ll (el-el) long-long con la conversione u (unsigned). (Funziona su Windows, GNU).

printf("%llu", 285212672);

11
O per essere precisi è per GNU libc e non funziona con il runtime C di Microsoft.
— Mark Baker,

168
Questa non è una cosa Linux / UNIX, il modificatore di lunghezza "ll" è stato aggiunto allo Standard C in C99, se non funziona in "Microsoft C", è perché non sono conformi agli standard.
— Robert Gamble,

12
Funziona per me in VS2008. Inoltre, per quanto mi ricordo, il compilatore MS C (quando impostato per compilare direttamente C) dovrebbe essere conforme alla progettazione C90; C99 ha introdotto alcune cose che non piacevano a tutti.
— ス ー パ ー フ ァ ミ コ ン

6
Una cosa da tenere a mente qui è che se si passano più long longargomenti printfe si utilizza il formato errato per uno di essi, ad esempio %dinvece di %lld, anche gli argomenti stampati dopo quello errato potrebbero essere completamente disattivati ​​(o persino causare un printfarresto anomalo ). In sostanza, gli argomenti variabili vengono passati a printf senza alcuna informazione sul tipo, quindi se la stringa di formato non è corretta, il risultato è imprevedibile.
— dmitrii,

1
Heard Herb Sutter ha dichiarato in un'intervista che i clienti di Microsoft non chiedono C99, quindi il loro compilatore C puro è stato congelato a C90. Questo vale se stai compilando come C. Se compili come C ++, come altri hanno già notato sopra, dovresti andare bene.
— ahcox,

90

Si consiglia di provare a utilizzare la libreria inttypes.h che ti da tipi come int32_t, int64_t, uint64_tecc È quindi possibile utilizzare le sue macro come ad esempio:

uint64_t x;
uint32_t y;

printf("x: %"PRId64", y: %"PRId32"\n", x, y);

Questo è "garantito" per non darti lo stesso problema long, unsigned long longecc., Dal momento che non devi indovinare quanti bit ci sono in ciascun tipo di dati.


laddove PRId64, PRId32le macro definite?
— happy_marmoset,

4
@happy_marmoset: sono definiti ininttypes.h
— Nathan Fellman il

4
Penso che tu abbia bisogno PRIu64e PRIu32per numeri interi senza segno.
— Lasse Kliemann,

1
È inttypes.hstandard? Non sarebbe stdint.h?
— MD XF,

2
Si noti che questi tipi di larghezza esatta sono opzionali , poiché esistono architetture che non hanno tipi interi di tali larghezze esatte. Sono obbligatori solo i tipi leastXe fastX(che possono effettivamente essere più ampi di quelli indicati).
— DevSolar,

78

%d-> per int

%u-> per unsigned int

%ld-> per long intolong

%lu-> per unsigned long into long unsigned intounsigned long

%lld-> per long long intolong long

%llu-> per unsigned long long intounsigned long long


Esiste un identificatore di formato come il numero di cifre da visualizzare, giustificazione sinistra o destra per% lld o% llu?
— Asam Padeh,

40

Per molto tempo (o __int64) usando MSVS, dovresti usare% I64d:

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

37

Questo perché% llu non funziona correttamente in Windows e% d non è in grado di gestire numeri interi a 64 bit. Suggerisco invece di usare PRIu64 e troverai anche portatile su Linux.

Prova questo invece:

#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;
}

Produzione

My number is 8 bytes wide and its value is 285212672. A normal number is 5.

+1 per il riferimento a PRIu64, che non avevo mai visto, ma questo non sembra portatile a Linux a 64 bit (almeno) perché PRIu64 si espande in "lu" anziché "llu".
— BD a Rivenhill,

8
E perché sarebbe male? Una lunghezza è un valore a 64 bit su Linux a 64 bit, come su tutti gli altri sistemi operativi tranne Windows.
— Ringding

@BDatRivenhill Linux / Unix utilizza LP64 in cui è lungo 64 bit
— phuclv

1
tuttavia, per renderlo più portatile, usa int64_tinvece perché potrebbero esserci delle implementazioni con long long long
— large that

questo dovrebbe essere al top! - un piccolo aggiornamento: errore: suffisso non valido su letterale; C ++ 11 richiede uno spazio tra letterale e identificativo [-Wreserved-user-definito-literal-letteral]
— tofutim

14

In Linux lo è %llue in Windows lo è%I64u

Anche se ho scoperto che non funziona in Windows 2000, sembra che ci sia un bug lì!


con windows, (o almeno, con il compilatore microsoft C per windows) c'è anche% I64d,% I32u e% I32d
— JustJeff

1
Cosa c'entra con Windows 2000? La libreria C è quella che gestisce printf.
— CMircea

1
Proprio quello che ho osservato. Ho scritto un'app che utilizzava questo costrutto e funzionava perfettamente su WinXP ma sputava immondizia su Win2k. Forse è qualcosa a che fare con una chiamata di sistema che la libreria C sta facendo al kernel, forse è qualcosa a che fare con Unicode, chi lo sa. Ricordo di aver dovuto aggirare il problema usando _i64tot () o qualcosa del genere.
— Adam Pierce,

7
Sembra che MS eserciti di nuovo la sua "libertà di innovare" ... ;-)
— Dronz,

Il problema Win2k / Win9x è probabilmente dovuto al fatto che il unsigned long longtipo di dati è relativamente nuovo (al momento, con lo standard C99) ma i compilatori C (incluso MinGW / GCC) che utilizzano il vecchio runtime Microsoft C che supportava solo le specifiche C89. Ho accesso solo a documenti API Windows molto vecchi e ragionevolmente recenti. Quindi è difficile dire esattamente quando è I64ustato abbandonato il supporto. Ma suona come l'era XP.
— veganaiZe


3

Oltre a ciò che la gente ha scritto anni fa:

  • potresti ricevere questo errore su gcc / mingw:

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

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

Quindi la tua versione di mingw non è predefinita su c99. Aggiungere questo flag del compilatore: -std=c99.


3

Apparentemente nessuno ha escogitato una soluzione multipiattaforma * da oltre un decennio dall'anno 2008, quindi aggiungerò la mia 😛. Per favore. (Scherzo. Non mi interessa.)

Soluzione: lltoa()

Come usare:

#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));

Esempio di OP:

#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;
}

A differenza della %lldstringa del formato di stampa, questa funziona per me con GCC a 32 bit su Windows.

*) Beh, quasi multipiattaforma. In MSVC, apparentemente è necessario _ui64toa()invece di lltoa().


1
Non ho lltoa.
— Antti Haapala,

1

Le cose non standard sono sempre strane :)

per la lunga porzione lunga sotto GNU è L, lloq

e sotto le finestre credo sia llsolo


1

Esadecimale:

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

Produzione:

64bit: FFFFFFFFFFFFFFFF

Molto bella! mi chiedevo come avrei potuto ottenerlo nella rappresentazione esadecimale
— 0xAK

Ma quasi tutti i compilatori C ++ e C danno l'avvertimento: avvertimento: uso del modificatore di lunghezza 'll' con carattere di tipo 'p' [-Wformat =]
— Seshadri R

2
questa risposta completamente rotta ha un comportamento doppiamente indefinito e non inizia nemmeno a rispondere alla domanda .
— Antti Haapala,

@AnttiHaapala Dici che questa risposta è completamente spezzata da un comportamento doppiamente indefinito, puoi elaborarla o devo semplicemente cancellarla? O tenerlo come un buon cattivo esempio?
— lama12345,

0

Bene, un modo è quello di compilarlo come x64 con VS2008

Funziona come ti aspetteresti:

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);

Per il codice a 32 bit, è necessario utilizzare l'identificatore di formato __int64 corretto% I64u. Così diventa.

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);

Questo codice funziona sia per il compilatore VS a 32 che a 64 bit.


Prova un numero a 64 bit effettivo anziché "285212672" e non credo che il primo esempio venga eseguito correttamente, compilato per qualsiasi destinazione.
— dyasta,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.