So drucken Sie portabel einen int64_t-Typ in C

Lesezeit: 7 Minuten

Benutzeravatar von rtacconi
rtaconi

Der C99-Standard hat Integer-Typen mit einer Bytegröße wie int64_t. Ich verwende Windows %I64d aktuelles Format (oder unsigned %I64u), wie:

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

und ich bekomme diese Compiler-Warnung:

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

Ich habe es versucht mit:

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

Aber ich bekomme die gleiche Warnung. Ich verwende diesen Compiler:

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

Welches Format sollte ich verwenden, um die Variable my_int ohne Warnung zu drucken?

  • Für C++ siehe stackoverflow.com/questions/8132399/how-to-printf-uint64-t

    – Antonio

    23. August 2016 um 9:02 Uhr

Benutzeravatar von ouah
ouah

Zum int64_t Typ:

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

zum uint64_t Typ:

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

kannst du auch verwenden PRIx64 hexadezimal drucken.

cppreference.com hat eine vollständige Auflistung der verfügbaren Makros für alle Typen einschließlich intptr_t (PRIxPTR). Es gibt separate Makros für scanf, wie z SCNd64.


Eine typische Definition von PRIu16 wäre "hu"sodass die implizite Verkettung von Zeichenfolgenkonstanten zur Kompilierzeit erfolgt.

Damit Ihr Code vollständig portierbar ist, müssen Sie verwenden PRId32 und so weiter zum Drucken int32_tund "%d" oder ähnliches zum Ausdrucken int.

  • Vollständige Liste der Formatierungsmakrokonstanten: en.cppreference.com/w/cpp/types/integer

    – Masood Khaari

    14. Mai 2013 um 10:45 Uhr

  • Und wenn Sie C++ unter Linux verwenden, stellen Sie sicher, dass Sie dies tun #define __STDC_FORMAT_MACROS vor dem Einschließen inttypes.h.

    – kl

    28. November 2014 um 8:50 Uhr

  • PRId64 ist ein Makro, das intern in übersetzt wird "lld". Es ist also so gut wie das Schreiben printf("%lld\n", t); Siehe Artikelbeschreibung : qnx.com/developers/docs/6.5.0/…

    – Gaurav

    14. August 2015 um 11:32 Uhr


  • @Gaurav, das stimmt auf einigen Plattformen, aber nicht auf allen. Auf meinem AMD64-Linux-Rechner ist PRId64 beispielsweise definiert als ld. Portabilität ist der Grund für das Makro.

    – Ethan T

    28. Juni 2016 um 15:06 Uhr

  • Ich denke, mit etwas mehr Aufwand hätten sie es noch unausstehlicher machen können

    – Paul P

    27. Oktober 2017 um 23:35 Uhr

Benutzeravatar von pmg
pmg

Der C99-Weg ist

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

Oder du könntest werfen!

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

Wenn Sie mit einer C89-Implementierung (insbesondere Visual Studio) feststecken, können Sie vielleicht eine Open Source verwenden <inttypes.h> (und <stdint.h>): http://code.google.com/p/msinttypes/

  • Wenn ich msinttypes vom code.google.com-Link verwende, muss ich __STDC_FORMAT_MACROS definieren. Siehe stackoverflow.com/questions/8132399/how-to-printf-uint64-t.

    – Ariscris

    28. Mai 2014 um 16:49 Uhr

  • Danke für den Hinweis, @ariscris. Es scheint jedoch, dass Makros nur für C++ erforderlich sind. Die Definitionen im verknüpften Code befinden sich in a #if !defined(__cplusplus) || defined(__STDC_FORMAT_MACROS)

    – pmg

    28. Mai 2014 um 17:08 Uhr


Benutzeravatar von pjhsea
pjhsea

Mit C99 die %j Der Längenmodifikator kann auch mit der printf-Funktionsfamilie verwendet werden, um Werte des Typs auszugeben int64_t und 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;
}

Kompilieren Sie diesen Code mit gcc -Wall -pedantic -std=c99 erzeugt keine Warnungen und das Programm gibt die erwartete Ausgabe aus:

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

Dies ist gem printf(3) auf meinem Linux-System (die Manpage sagt das ausdrücklich j wird verwendet, um eine Umwandlung in an anzuzeigen intmax_t oder uintmax_t; in meiner stdint.h beides int64_t und intmax_t werden auf genau die gleiche Weise typdefiniert, und ähnlich für uint64_t). Ich bin mir nicht sicher, ob dies perfekt auf andere Systeme übertragbar ist.

  • Wenn %jd druckt ein intmax_twäre der korrekte Aufruf printf("a=%jd (0x%jx)", (intmax_t) a, (intmax_t) a). Dafür gibt es keine Garantie int64_t und intmax_t sind vom gleichen Typ, und wenn sie es nicht sind, ist das Verhalten undefiniert.

    – Benutzer4815162342

    25. April 2013 um 17:56 Uhr

  • Sie können tragbar verwenden %jd zu drucken int64_t Werte wenn Sie konvertieren sie explizit in intmax_t bevor Sie sie weitergeben printf: printf("a=%jd\n", (intmax_t)a). Dies vermeidet die (IMHO) Hässlichkeit des <inttypes.h> Makros. Dies setzt natürlich voraus, dass Ihre Implementierung dies unterstützt %jd, int64_tund intmax_tdie alle von C99 hinzugefügt wurden.

    – Keith Thompson

    12. August 2013 um 19:03 Uhr

  • @KeithThompson ‘Häßlichkeit’ drückt es viel, viel, viel zu freundlich aus, Kumpel. Es ist absolut scheußlich. Es ist gruselig. Es ist ekelerregend. Es ist peinlich, was es ist. Oder zumindest sollten sie sich schämen, die Leute, die das eingeführt haben. Ich habe diese Makros noch nie gesehen, aber tun Sie, was diese Antwort und die Kommentare – einschließlich Ihrer – vorschlagen.

    – Pryftan

    3. Dezember 2019 um 22:59 Uhr

  • @ Pryftan Ich nicht ziemlich finde sie genauso hässlich wie du – und ich bin mir überhaupt nicht sicher, wie sie ohne Sprachänderungen weniger hässlich definiert werden könnten.

    – Keith Thompson

    4. Dezember 2019 um 2:28 Uhr

  • @KeithThompson Nun, ich bin dankbar, dass du zumindest das Wort “ziemlich” betont hast. Nun, eigentlich ist es egal. Ich verstehe nicht, warum die Makros dort sein müssen. Wie Sie sagen, können Sie portabel … usw. Aber dann finde ich auch, dass die Erhöhung der Anzahl der Schlüsselwörter auch aus dem Ruder gelaufen ist.

    – Pryftan

    14. Dezember 2019 um 20:46 Uhr

Aus der eingebetteten Welt kommend, wo sogar uclibc nicht immer verfügbar ist, und Code wie

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

druckt du Mist oder funktioniert überhaupt nicht — ich benutze immer einen kleinen Helfer, der es mir erlaubt, richtig uint64_t hex zu dumpen:

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

Benutzeravatar von benlong
Benlang

Verwenden Sie in der Windows-Umgebung

%I64d

unter Linux verwenden

%lld

  • %lld ist das Format für long long intwelches ist nicht unbedingt gleich int64_t. <stdint.h> hat ein Makro für das richtige Format für int64_t; Siehe Ouahs Antwort.

    – Keith Thompson

    12. August 2013 um 19:05 Uhr


  • @KeithThompson Aber da long long ist mindestens 64-Bit, printf("%lld", (long long)x); sollte funktionieren, außer vielleicht für -0x8000000000000000, was nicht als darstellbar wäre long long wenn dieser Typ kein Zweierkomplement verwendet.

    – Pascal Cuoq

    12. August 2013 um 20:54 Uhr

  • @PascalCuoq: Ja, es sollte mit der Besetzung funktionieren (und die von Ihnen erwähnte Ausnahme ist sehr unwahrscheinlich und gilt nur für ein System, das Zweierkomplement unterstützt, es aber nicht verwendet long long).

    – Keith Thompson

    12. August 2013 um 21:10 Uhr

Benutzeravatar von HarshaD
HarshaD

Stolperte über diese Frage, als ich nach einer Möglichkeit suchte, 64-Bit-Zahlen in Hex anzuzeigen:

Herausgefunden, dass Sie verwenden können:

0x%016llx – funktioniert zumindest mit meinem Compiler (aarch64 GCC 7.3.0)

  • %lld ist das Format für long long intwelches ist nicht unbedingt gleich int64_t. <stdint.h> hat ein Makro für das richtige Format für int64_t; Siehe Ouahs Antwort.

    – Keith Thompson

    12. August 2013 um 19:05 Uhr


  • @KeithThompson Aber da long long ist mindestens 64-Bit, printf("%lld", (long long)x); sollte funktionieren, außer vielleicht für -0x8000000000000000, was nicht als darstellbar wäre long long wenn dieser Typ kein Zweierkomplement verwendet.

    – Pascal Cuoq

    12. August 2013 um 20:54 Uhr

  • @PascalCuoq: Ja, es sollte mit der Besetzung funktionieren (und die von Ihnen erwähnte Ausnahme ist sehr unwahrscheinlich und gilt nur für ein System, das Zweierkomplement unterstützt, es aber nicht verwendet long long).

    – Keith Thompson

    12. August 2013 um 21:10 Uhr

//VC6.0 (386 und besser)

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

Grüße.

1433720cookie-checkSo drucken Sie portabel einen int64_t-Typ in C

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy