Come stampare un tipo int64_t in C


298

Lo standard C99 ha tipi interi con dimensione byte come int64_t. Sto usando il seguente codice:

#include <stdio.h>
#include <stdint.h>
int64_t my_int = 999999999999999999;
printf("This is my_int: %I64d\n", my_int);

e ricevo questo avviso del compilatore:

warning: format ‘%I64d expects type int’, but argument 2 has type int64_t

Ho provato con:

printf("This is my_int: %lld\n", my_int); // long long decimal

Ma ricevo lo stesso avvertimento. Sto usando questo compilatore:

~/dev/c$ cc -v
Using built-in specs.
Target: i686-apple-darwin10
Configured with: /var/tmp/gcc/gcc-5664~89/src/configure --disable-checking --enable-werror --prefix=/usr --mandir=/share/man --enable-languages=c,objc,c++,obj-c++ --program-transform-name=/^[cg][^.-]*$/s/$/-4.2/ --with-slibdir=/usr/lib --build=i686-apple-darwin10 --program-prefix=i686-apple-darwin10- --host=x86_64-apple-darwin10 --target=i686-apple-darwin10 --with-gxx-include-dir=/include/c++/4.2.1
Thread model: posix
gcc version 4.2.1 (Apple Inc. build 5664)

Quale formato devo usare per stampare la variabile my_int senza un avviso?


Risposte:


420

Per int64_ttipo:

#include <inttypes.h>
int64_t t;
printf("%" PRId64 "\n", t);

per uint64_ttipo:

#include <inttypes.h>
uint64_t t;
printf("%" PRIu64 "\n", t);

puoi anche usare PRIx64per stampare in formato esadecimale.

cppreference.com ha un elenco completo di macro disponibili per tutti i tipi incluso intptr_t( PRIxPTR). Ci sono macro separate per scanf, come SCNd64.


Una definizione tipica di PRIu16 sarebbe "hu", quindi la concatenazione di stringhe implicite avviene al momento della compilazione.

Affinché il codice sia completamente portatile, è necessario utilizzare PRId32e così via per la stampa int32_te "%d"simili per la stampa int.


18
Elenco completo delle costanti macro di formattazione: en.cppreference.com/w/cpp/types/integer
Massood Khaari

12
E, se si utilizza C ++ su Linux, assicurarsi di #define __STDC_FORMAT_MACROSprima di includere inttypes.h.
CSL

17
PRId64è una macro tradotta internamente "lld". Quindi, è buono come scrivere printf("%lld\n", t);Vedi la descrizione: qnx.com/developers/docs/6.5.0/…
Gaurav

24
@ Gaurav, questo è vero su alcune piattaforme, ma non su tutti. Sulla mia macchina Linux amd64, ad esempio, PRId64 è definito come ld. La portabilità è la ragione della macro.
Ethan T,

10
Penso che con qualche sforzo in più avrebbero potuto renderlo ancora più odioso
Pavel P

65

Il modo C99 è

#include <inttypes.h>
int64_t my_int = 999999999999999999;
printf("%" PRId64 "\n", my_int);

Oppure potresti lanciare!

printf("%ld", (long)my_int);
printf("%lld", (long long)my_int); /* C89 didn't define `long long` */
printf("%f", (double)my_int);

Se sei bloccato con un'implementazione C89 (in particolare Visual Studio) puoi forse usare un open source <inttypes.h>(e <stdint.h>): http://code.google.com/p/msinttypes/


Quando utilizzo msinttypes dal link code.google.com, devo definire __STDC_FORMAT_MACROS. Vedi stackoverflow.com/questions/8132399/how-to-printf-uint64-t .
ariscris,

Grazie per il testa a testa, @ariscris. Sembra che la macro sia richiesta solo per C ++. Le definizioni nel codice collegato si trovano in a#if !defined(__cplusplus) || defined(__STDC_FORMAT_MACROS)
pmg

19

Con C99 il %jmodificatore di lunghezza può essere utilizzato anche con la famiglia di funzioni printf per stampare valori di tipo int64_te uint64_t:

#include <stdio.h>
#include <stdint.h>

int main(int argc, char *argv[])
{
    int64_t  a = 1LL << 63;
    uint64_t b = 1ULL << 63;

    printf("a=%jd (0x%jx)\n", a, a);
    printf("b=%ju (0x%jx)\n", b, b);

    return 0;
}

La compilazione di questo codice con gcc -Wall -pedantic -std=c99non produce avvisi e il programma stampa l'output previsto:

a=-9223372036854775808 (0x8000000000000000)
b=9223372036854775808 (0x8000000000000000)

Questo è secondo printf(3)il mio sistema Linux (la pagina man dice specificamente che jviene usato per indicare una conversione in un intmax_to uintmax_t; nel mio stdint.h, entrambi int64_te intmax_tsono digitati esattamente nello stesso modo, e allo stesso modo per uint64_t). Non sono sicuro che questo sia perfettamente portatile per altri sistemi.


12
Se si %jdpreme an intmax_t, l'invocazione corretta sarebbe printf("a=%jd (0x%jx)", (intmax_t) a, (intmax_t) a). Non v'è alcuna garanzia che int64_te intmax_tsono dello stesso tipo, e se non lo sono, non è definito il comportamento.
user4815162342

4
È portabile possibile utilizzare %jdper stampare int64_ti valori se li converte in modo esplicito a intmax_tprima di passarli a printf: printf("a=%jd\n", (intmax_t)a). Questo evita la bruttezza (IMHO) delle <inttypes.h>macro. Naturalmente questo presuppone che i vostri supporti di implementazione %jd, int64_te intmax_t, ognuno dei quali sono stati aggiunti da C99.
Keith Thompson,

2
@KeithThompson 'Bruttezza' lo sta mettendo molto più o meno gentilmente amico. È assolutamente orribile. È orribile. È nauseabondo. È imbarazzante è quello che è. O almeno dovrebbero essere imbarazzati, il lotto che lo ha introdotto. Non ho mai visto queste macro, ma faccio ciò che suggeriscono questa risposta e i commenti, incluso il tuo.
Pryftan,

@Pryftan non abbastanza li trovo abbastanza brutto come si fa - e io non sono affatto sicuro come potrebbero essere definiti in maniera meno brutto senza cambiamenti linguistici.
Keith Thompson il

@KeithThompson Beh, sono grato che almeno tu abbia sottolineato la parola "abbastanza". Beh, in realtà non importa. Non vedo perché le macro debbano essere lì però. Come dici tu puoi portabilmente ... Ecc. Ma poi scopro anche che l'aumento del numero di parole chiave è sfuggito di mano.
Pryftan,

12

Proveniente dal mondo embedded, dove anche uclibc non è sempre disponibile, e codice simile

uint64_t myval = 0xdeadfacedeadbeef; printf("%llx", myval);

ti sta stampando una merda o non funziona affatto - uso sempre un piccolo aiuto, che mi consente di scaricare correttamente uint64_t hex:

#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>

char* ullx(uint64_t val)
{
    static char buf[34] = { [0 ... 33] = 0 };
    char* out = &buf[33];
    uint64_t hval = val;
    unsigned int hbase = 16;

    do {
        *out = "0123456789abcdef"[hval % hbase];
        --out;
        hval /= hbase;
    } while(hval);

    *out-- = 'x', *out = '0';

    return out;
}

Se stai affrontando questo problema per un'applicazione incorporata, questo è quello che stai cercando. Questa soluzione ha funzionato per me. Thnx @ataraxic.
Logan859,

8

In ambiente Windows, utilizzare

%I64d

in Linux, utilizzare

%lld

18
%lldè il formato per long long int, che non è necessariamente lo stesso di int64_t. <stdint.h>ha una macro per il formato corretto per int64_t; vedere la risposta di ouah .
Keith Thompson,

@KeithThompson Tuttavia, poiché long longè almeno a 64 bit, printf("%lld", (long long)x);dovrebbe funzionare, tranne forse per -0x8000000000000000, che non potrebbe essere rappresentabile come long longse quel tipo non utilizzasse il complemento a due.
Pascal Cuoq,

@PascalCuoq: Sì, dovrebbe funzionare con il cast (e l'eccezione che menzioni è molto improbabile, si applica solo a un sistema che supporta il complemento a due ma per cui non lo usa long long).
Keith Thompson,

-3

//VC6.0 (386 e migliore)

    __int64 my_qw_var = 0x1234567890abcdef;

    __int32 v_dw_h;
    __int32 v_dw_l;

    __asm
        {
            mov eax,[dword ptr my_qw_var + 4]   //dwh
            mov [dword ptr v_dw_h],eax

            mov eax,[dword ptr my_qw_var]   //dwl
            mov [dword ptr v_dw_l],eax

        }
        //Oops 0.8 format
    printf("val = 0x%0.8x%0.8x\n", (__int32)v_dw_h, (__int32)v_dw_l);

Saluti.

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.