Comment printf uint64_t? Échec avec: "faux"% "à la fin du format"

133

J'ai écrit un code de test très simple de printf uint64_t:

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

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

J'utilise ubuntu 11.10 (64 bits) et gcc version 4.6.1 pour le compiler, mais j'ai échoué:

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
la source
1
Il semble que vous compilez du code C en C ++, c'est votre erreur. Si vous renommez votre fichier main.cet le compilez avec gcc, tout devrait fonctionner correctement.
Jens Gustedt
Idem sans erreur: stackoverflow.com/questions/9225567/…
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
Avec gcc ou clang, c'est une bonne idée de spécifier -std=c11ou la version de la norme que vous utilisez. Cela rattrape cela et d'autres erreurs. Je recommande aussi -Wall -Wextra -Wpedantic -Wconversionau moins.
Davislor

Réponses:

164

La norme ISO C99 spécifie que ces macros ne doivent être définies que si elles sont explicitement demandées.

#define __STDC_FORMAT_MACROS
#include <inttypes.h>

... now PRIu64 will work
Volonté
la source
@Dan, n'oubliez pas de marquer la réponse comme acceptée (cliquez sur l'image de la coche à gauche) si elle a résolu votre problème.
zneak
9
Hm, il suffit d'inclure l'en-tête. La __STDC_FORMAT_MACROSmacro n'est requise que pour l'inclusion dans C ++.
Jens Gustedt
15
@Jens: En effet; __STDC_FORMAT_MACROSapparaît uniquement dans une note de bas de page en C99, suggérant que C ++ ne définisse ces macros qu'en présence de la requête. Cependant, le comité C ++ a choisi d'ignorer la suggestion: par exemple dans le projet n3242, 27.9.2 / 3: Note: Les macros définies par <cinttypes> sont fournies sans condition. En particulier, le symbole __STDC_FORMAT_MACROS, mentionné dans la note de bas de page 182 du standard C, ne joue aucun rôle en C ++. Ainsi, lorsque les compilateurs rattraperont leur retard, nous n'aurons pas besoin __STDC_FORMAT_MACROSde C ou C ++.
John Marshall
3
@John Marshall g ++ 4.7.3 semble exiger la macro, même lorsque <inttypes.h> est inclus.
crockeea
4
@Eric: Apparemment, g ++ 4.7.3 n'avait pas rattrapé son retard! En fait, vous l'utilisez probablement avec une version glibc antérieure à cette correction de bogue . Comme indiqué dans ce rapport de la glibc, la libstdc ++ de votre g ++ 4.7.3 a du code pour contourner ce problème. Si vous compilez avec -std=c++0xet peut-être #include <cinttypes> plutôt que <inttypes.h>, je crois que cela fournirait les macros de format sans que vous fournissiez __STDC_FORMAT_MACROS.
John Marshall
4

Lors de la compilation de memcached sous Centos 5.xi a eu le même problème.

La solution consiste à mettre à niveau gcc et g ++ au moins vers la version 4.4.

Assurez-vous que votre CC / CXX est défini (exporté) sur les bons binaires avant la compilation.

Anders Eliasson
la source
1

Puisque vous avez inclus la balise C ++, vous pouvez utiliser la bibliothèque {fmt} et éviter complètement la PRIu64macro et d'autres printfproblèmes:

#include <fmt/core.h>

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

La fonction de formatage basée sur cette bibliothèque est proposée pour la normalisation en C ++ 20: P0645 .

Avertissement : je suis l'auteur de {fmt}.

vitaut
la source
Cool! Vient-il aussi quelque chose de similaire sscanf?
ceztko
Très probablement. Nous étudions la possibilité de remplacer scanf.
vitaut
Génial! Je me demande également s'il y a des progrès vers une version locale indépendante et / ou sélectionnable de std::to_string(). La page cppreference renvoie toujours uniquement vers std::to_chars(), ce qui n'est pas vraiment ce dont les gens ont besoin. Je me demande si fmtet / ou c ++ 20 s'en occupe ou pas encore.
ceztko
std::to_stringrestera probablement tel std::formatquel , mais vous permet de contrôler si vous souhaitez utiliser la locale ou non (et par défaut, elle n'utilise pas la locale).
vitaut