Wie drucke ich uint64_t? Schlägt fehl mit: "falsches abschließendes '%' im Format"

133

Ich habe einen sehr einfachen Testcode von printf uint64_t geschrieben:

#include <inttypes.h>
#include <stdio.h>

int main()
{
  uint64_t ui64 = 90;
  printf("test uint64_t : %" PRIu64 "\n", ui64);
  return 0;
}

Ich verwende Ubuntu 11.10 (64 Bit) und gcc Version 4.6.1, um es zu kompilieren, aber es ist fehlgeschlagen:

main.cpp: In function int main()’:
main.cpp:9:30: error: expected ‘)’ before PRIu64
main.cpp:9:47: warning: spurious trailing ‘%’ in format [-Wformat]
Dan
quelle
1
Es scheint, dass Sie C-Code als C ++ kompilieren, das ist Ihr Fehler. Wenn Sie Ihre Datei umbenennen main.cund mit gcc kompilieren, sollte alles einwandfrei funktionieren.
Jens Gustedt
Gleiches ohne Fehler: stackoverflow.com/questions/9225567/…
Ciro Santilli 法轮功 冠状 病 六四 事件 8
Mit gcc oder clang ist es eine gute Idee, -std=c11die Version des von Ihnen verwendeten Standards anzugeben . Das fängt diesen und andere Fehler auf. Ich empfehle auch -Wall -Wextra -Wpedantic -Wconversionzumindest.
Davislor

Antworten:

164

Der ISO C99-Standard legt fest, dass diese Makros nur definiert werden dürfen, wenn dies ausdrücklich angefordert wird.

#define __STDC_FORMAT_MACROS
#include <inttypes.h>

... now PRIu64 will work
Wille
quelle
@Dan, vergessen Sie nicht, die Antwort als akzeptiert zu markieren (klicken Sie auf das Häkchen links), wenn das Problem dadurch behoben wurde.
Zneak
9
Hm, nur den Header einzuschließen sollte ausreichen. Das __STDC_FORMAT_MACROSMakro wird nur für die Aufnahme in C ++ benötigt.
Jens Gustedt
15
@Jens: In der Tat; __STDC_FORMAT_MACROSwird in C99 nur in einer Fußnote angezeigt, was darauf hindeutet, dass C ++ diese Makros nur bei Vorhandensein der Anforderung definiert. Das C ++ - Komitee hat sich jedoch entschieden, den Vorschlag zu ignorieren: z. B. im Entwurf von n3242, 27.9.2 / 3: Hinweis: Die durch <cinttypes> definierten Makros werden unbedingt bereitgestellt. Insbesondere das in Fußnote 182 des C-Standards erwähnte Symbol __STDC_FORMAT_MACROS spielt in C ++ keine Rolle. Wenn die Compiler aufholen, brauchen wir __STDC_FORMAT_MACROSweder C noch C ++.
John Marshall
3
@ John Marshall g ++ 4.7.3 scheint das Makro zu erfordern, auch wenn <inttypes.h> enthalten ist.
Crockeea
4
@ Eric: Anscheinend hatte g ++ 4.7.3 nicht aufgeholt! Wahrscheinlich verwenden Sie es sogar mit einer glibc-Version, die vor dieser Fehlerbehebung erstellt wurde . Wie in diesem glibc-Bericht erläutert, verfügt libstdc ++ in g ++ 4.7.3 über Code, um dieses Problem zu umgehen. Wenn Sie mit -std=c++0x<cinttypes> anstelle von <inttypes.h> kompilieren und möglicherweise #include verwenden, werden die Formatmakros meiner Meinung nach ohne Ihre Angabe bereitgestellt __STDC_FORMAT_MACROS.
John Marshall
4

Beim Kompilieren von Memcached unter Centos 5.xi trat das gleiche Problem auf.

Die Lösung besteht darin, gcc und g ++ mindestens auf Version 4.4 zu aktualisieren.

Stellen Sie vor dem Kompilieren sicher, dass Ihr CC / CXX auf die richtigen Binärdateien eingestellt (exportiert) ist.

Anders Eliasson
quelle
1

Da Sie das C ++ - Tag eingefügt haben, können Sie die {fmt} -Bibliothek verwenden und das PRIu64Makro und andere printfProbleme insgesamt vermeiden :

#include <fmt/core.h>

int main() {
  uint64_t ui64 = 90;
  fmt::print("test uint64_t : {}\n", ui64);
}

Die auf dieser Bibliothek basierende Formatierungsfunktion wird zur Standardisierung in C ++ 20: P0645 vorgeschlagen .

Haftungsausschluss : Ich bin der Autor von {fmt}.

vitaut
quelle
Cool! Kommt es auch so ähnlich sscanf?
Ceztko
Möglicherweise. Wir prüfen die Möglichkeit des Austauschs scanf.
Vitaut
Toll! Ich frage mich auch, ob es Fortschritte in Richtung einer vom Gebietsschema unabhängigen und / oder vom Gebietsschema auswählbaren Version von gibt std::to_string(). Die cppreference-Seite verlinkt immer noch nur auf std::to_chars(), was die Leute nicht wirklich brauchen. Ich frage mich, ob fmtund / oder c ++ 20 damit umgehen oder noch nicht.
Ceztko
std::to_stringwird wahrscheinlich unverändert bleiben, aber std::formatSie können steuern, ob das Gebietsschema verwendet werden soll oder nicht (und standardmäßig wird das Gebietsschema nicht verwendet).
Vitaut