Como imprimir uint64_t? Falha com: "rastreamento espúrio '%' em formato"

133

Eu escrevi um código de teste muito simples 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;
}

Eu uso o ubuntu 11.10 (64 bits) e a versão 4.6.1 do gcc para compilá-lo, mas falhei:

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
fonte
1
Parece que você está compilando o código C como C ++, esse é o seu erro. Se você renomear seu arquivo main.ce compilá-lo com o gcc, tudo funcionará bem.
Jens Gustedt
Mesmo sem erro: stackoverflow.com/questions/9225567/...
Ciro Santilli郝海东冠状病六四事件法轮功
Com o gcc ou o clang, é uma boa ideia especificar -std=c11ou a versão do padrão que você está usando. Isso pega esse e outros erros. Eu também recomendo -Wall -Wextra -Wpedantic -Wconversionpelo menos.
Davislor

Respostas:

164

O padrão ISO C99 especifica que essas macros devem ser definidas apenas se solicitadas explicitamente.

#define __STDC_FORMAT_MACROS
#include <inttypes.h>

... now PRIu64 will work
Vai
fonte
@ Dan, não se esqueça de marcar a resposta como aceita (clique na imagem da marca de seleção à esquerda) se resolver o seu problema.
zneak
9
Hum, apenas incluir o cabeçalho deve ser suficiente. A __STDC_FORMAT_MACROSmacro é necessária apenas para inclusão no C ++.
Jens Gustedt
15
@ Jens: De fato; __STDC_FORMAT_MACROSaparece apenas em uma nota de rodapé no C99, sugerindo que o C ++ apenas define essas macros na presença da solicitação. No entanto, o comitê C ++ optou por ignorar a sugestão: por exemplo, no rascunho n3242, 27.9.2 / 3: Nota: As macros definidas por <cinttypes> são fornecidas incondicionalmente. Em particular, o símbolo __STDC_FORMAT_MACROS, mencionado na nota de rodapé 182 do padrão C, não desempenha nenhum papel no C ++. Portanto, quando os compiladores os alcançarem, não precisaremos de __STDC_FORMAT_MACROSC ou C ++.
John Marshall
3
@John Marshall g ++ 4.7.3 parece exigir a macro, mesmo quando <inttypes.h> está incluído.
Crockeea # 31/13
4
@ Eric: Aparentemente, o g ++ 4.7.3 não havia sido pego! De fato, provavelmente você o está usando com uma versão glibc que antecede essa correção de bug . Conforme discutido no relatório glibc, o libstdc ++ do g ++ 4.7.3 possui código para solucionar esse problema. Se você compilar com -std=c++0xe talvez # incluir <cinttypes> em vez de <inttypes.h>, acredito que forneceria as macros de formato sem você fornecer __STDC_FORMAT_MACROS.
John Marshall
4

Ao compilar o memcached no Centos 5.xi, ocorreu o mesmo problema.

A solução é atualizar o gcc e o g ++ para a versão 4.4, pelo menos.

Verifique se seu CC / CXX está definido (exportado) para os binários corretos antes de compilar.

Anders Eliasson
fonte
1

Como você incluiu a tag C ++, você pode usar a biblioteca {fmt} e evitar completamente a PRIu64macro e outros printfproblemas:

#include <fmt/core.h>

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

O recurso de formatação baseado nesta biblioteca é proposto para padronização em C ++ 20: P0645 .

Isenção de responsabilidade : sou o autor de {fmt}.

vitaut
fonte
Legal! Também está chegando algo parecido sscanf?
Ceztko
Bem possível. Estamos investigando a possibilidade de substituição scanf.
Vitaut 28/11/19
Ótimo! Também me pergunto se há progresso em direção a uma versão independente e / ou selecionável por localidade std::to_string(). A página cppreference ainda possui um link apenas std::to_chars(), o que não é realmente o que as pessoas precisam. Gostaria de saber se fmte / ou c ++ 20 lidam com isso ou não ainda.
Ceztko # 28/19
std::to_stringprovavelmente permanecerá como está, mas std::formatpermite que você controle se deve usar o código do idioma ou não (e, por padrão, ele não usa o código do idioma).
vitaut 28/11/19