Comment imprimer un type int64_t en C

298

La norme C99 a des types entiers avec une taille d'octets comme int64_t. J'utilise le code suivant:

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

et je reçois cet avertissement du compilateur:

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

J'ai essayé avec:

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

Mais je reçois le même avertissement. J'utilise ce compilateur:

~/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)

Quel format dois-je utiliser pour imprimer ma variable int sans avoir d'avertissement?

rtacconi
la source

Réponses:

420

Pour int64_ttype:

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

pour uint64_ttype:

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

vous pouvez également utiliser PRIx64pour imprimer en hexadécimal.

cppreference.com a une liste complète des macros disponibles pour tous les types, y compris intptr_t( PRIxPTR). Il existe des macros distinctes pour scanf, comme SCNd64.


Une définition typique de PRIu16 serait "hu", donc la concaténation implicite à constante de chaîne se produit au moment de la compilation.

Pour que votre code soit entièrement portable, vous devez utiliser PRId32et ainsi de suite pour l'impression int32_tet / "%d"ou similaire pour l'impression int.

ouah
la source
18
Liste complète des constantes de macro de formatage: en.cppreference.com/w/cpp/types/integer
Massood Khaari
12
Et, si vous utilisez C ++ sur Linux, assurez-vous de l' #define __STDC_FORMAT_MACROSinclure avant inttypes.h.
csl
17
PRId64est une macro qui se traduit en interne par "lld". Donc, c'est aussi bien que d'écrire printf("%lld\n", t);Voir la description: qnx.com/developers/docs/6.5.0/…
Gaurav
24
@Gaurav, c'est vrai sur certaines plateformes, mais pas sur toutes. Sur ma machine Linux amd64, par exemple, PRId64 est défini comme ld. La portabilité est la raison de la macro.
Ethan T
10
Je pense qu'avec un effort supplémentaire, ils auraient pu le rendre encore plus désagréable
Pavel P
65

La méthode C99 est

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

Ou vous pouvez lancer!

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

Si vous êtes coincé avec une implémentation C89 (notamment Visual Studio), vous pouvez peut-être utiliser une source ouverte <inttypes.h>(et <stdint.h>): http://code.google.com/p/msinttypes/

pmg
la source
Lors de l'utilisation de msinttypes à partir du lien code.google.com, je dois définir __STDC_FORMAT_MACROS. Voir stackoverflow.com/questions/8132399/how-to-printf-uint64-t .
ariscris
Merci pour l'avertissement, @ariscris. Il semble cependant que la macro ne soit requise que pour C ++. Les définitions dans le code lié à sont à l'intérieur d'un#if !defined(__cplusplus) || defined(__STDC_FORMAT_MACROS)
pmg
19

Avec C99, le %jmodificateur de longueur peut également être utilisé avec la famille de fonctions printf pour imprimer des valeurs de type int64_tet 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 compilation de ce code avec gcc -Wall -pedantic -std=c99ne produit aucun avertissement et le programme imprime la sortie attendue:

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

Ceci est conforme à printf(3)sur mon système Linux (la page de manuel indique spécifiquement qu'elle jest utilisée pour indiquer une conversion en intmax_tou uintmax_t; dans mon stdint.h, les deux int64_tet intmax_tsont typés par défaut de la même manière et de la même manière pour uint64_t). Je ne suis pas sûr que ce soit parfaitement portable sur d'autres systèmes.

pjhsea
la source
12
Si %jdprnts an intmax_t, l'invocation correcte serait printf("a=%jd (0x%jx)", (intmax_t) a, (intmax_t) a). Il n'y a aucune garantie que int64_tet intmax_tsont du même type, et s'ils ne le sont pas, le comportement n'est pas défini.
user4815162342
4
Vous pouvez utiliser portably %jdpour imprimer des int64_tvaleurs si vous les convertir explicitement intmax_tavant de les transmettre à printf: printf("a=%jd\n", (intmax_t)a). Cela évite la laideur (à mon humble avis) des <inttypes.h>macros. Bien sûr , cela suppose que vos supports de mise en œuvre %jd, int64_tet intmax_t, qui ont tous été ajoutés par C99.
Keith Thompson
2
@KeithThompson 'La laideur' est en train de le mettre bien trop loin bien trop bien. C'est absolument hideux. C'est horrible. C'est écoeurant. C'est embarrassant, c'est ce que c'est. Ou du moins, ils devraient être gênés, le sort qui a introduit cela. Je n'ai jamais vu ces macros, mais faites ce que cette réponse et les commentaires - les vôtres inclus - suggèrent.
Pryftan
@Pryftan Je ne les trouve pas tout à fait aussi laids que vous - et je ne sais pas du tout comment ils pourraient être définis de manière moins laide sans changement de langue.
Keith Thompson
@KeithThompson Eh bien, je vous remercie au moins de mettre l'accent sur le mot «tout à fait». En fait, cela n'a pas d'importance. Je ne vois pas pourquoi les macros doivent être là cependant. Comme vous le dites, vous pouvez le faire de manière portable ... Etc. Mais ensuite, je trouve également que l'augmentation du nombre de mots clés est devenue incontrôlable.
Pryftan
12

Venant du monde embarqué, où même uclibc n'est pas toujours disponible, et du code comme

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

est en train d'imprimer des conneries ou ne fonctionne pas du tout - j'utilise toujours un petit assistant, qui me permet de vider correctement 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;
}
ataraxique
la source
Si vous rencontrez ce problème pour une application intégrée, c'est ce que vous recherchez. Cette solution a fonctionné pour moi. Thnx @ataraxic.
Logan859
8

Dans un environnement Windows, utilisez

%I64d

sous Linux, utilisez

%lld
benlong
la source
18
%lldest le format de long long int, qui n'est pas nécessairement le même que int64_t. <stdint.h>a une macro pour le format correct pour int64_t; voir la réponse de ouah .
Keith Thompson
@KeithThompson Cependant, comme long longc'est au moins 64 bits, cela printf("%lld", (long long)x);devrait fonctionner, sauf peut-être pour -0x8000000000000000, qui ne pourrait pas être représentable comme long longsi ce type n'utilisait pas le complément à deux.
Pascal Cuoq
@PascalCuoq: Oui, cela devrait fonctionner avec le casting (et l'exception que vous mentionnez est très peu probable, ne s'appliquant qu'à un système qui prend en charge le complément à deux mais ne l'utilise pas pour long long).
Keith Thompson
-3

//VC6.0 (386 et mieux)

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

Cordialement.

Daniel Ag
la source