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.