¿Cómo imprimir uint64_t? Falla con: "formato falso '%' en formato"

133

Escribí un código de prueba muy 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;
}

Utilizo ubuntu 11.10 (64 bit) y gcc versión 4.6.1 para compilarlo, pero fallé:

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
fuente
1
Parece que estás compilando código C como C ++, ese es tu error. Si cambia el nombre de su archivo main.cy lo compila con gcc, todo debería funcionar bien.
Jens Gustedt
Lo mismo sin error: stackoverflow.com/questions/9225567/…
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
Con gcc o clang, es una buena idea especificar -std=c11o la versión del estándar que está utilizando. Eso atrapa este y otros errores. También recomiendo -Wall -Wextra -Wpedantic -Wconversional menos.
Davislor

Respuestas:

164

El estándar ISO C99 especifica que estas macros solo deben definirse si se solicitan explícitamente.

#define __STDC_FORMAT_MACROS
#include <inttypes.h>

... now PRIu64 will work
Será
fuente
@ Dan, no olvides marcar la respuesta como aceptada (haz clic en la imagen de marca de verificación a la izquierda) si resolvió tu problema.
zneak
9
Hm, solo incluir el encabezado debería ser suficiente. La __STDC_FORMAT_MACROSmacro solo es necesaria para su inclusión en C ++.
Jens Gustedt
15
@Jens: De hecho; __STDC_FORMAT_MACROSaparece solo en una nota al pie en C99, lo que sugiere que C ++ solo define estas macros en presencia de la solicitud. Sin embargo, el comité de C ++ decidió ignorar la sugerencia: por ejemplo, en el borrador n3242, 27.9.2 / 3: Nota: Las macros definidas por <cinttypes> se proporcionan incondicionalmente. En particular, el símbolo __STDC_FORMAT_MACROS, mencionado en la nota al pie 182 del estándar C, no juega ningún papel en C ++. Entonces, cuando los compiladores se pongan al día, no necesitaremos __STDC_FORMAT_MACROSC ni C ++.
John Marshall
3
@John Marshall g ++ 4.7.3 parece requerir la macro, incluso cuando se incluye <inttypes.h>.
crockeea
44
@Eric: ¡Al parecer, g ++ 4.7.3 no se había puesto al día! De hecho, probablemente lo esté utilizando con una versión glibc que es anterior a esta corrección de errores . Como se discutió en ese informe de glibc, su libstdc ++ de g ++ 4.7.3 tiene código para solucionar este problema. Si compila -std=c++0xy tal vez #incluye <cinttypes> en lugar de <inttypes.h>, creo que proporcionaría las macros de formato sin que usted proporcione __STDC_FORMAT_MACROS.
John Marshall
4

Al compilar memcached en Centos 5.xi, tuve el mismo problema.

La solución es actualizar gcc y g ++ a la versión 4.4 al menos.

Asegúrese de que su CC / CXX esté configurado (exportado) en binarios correctos antes de compilar.

Anders Eliasson
fuente
1

Como ha incluido la etiqueta C ++, puede usar la biblioteca {fmt} y evitar la PRIu64macro y otros printfproblemas por completo:

#include <fmt/core.h>

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

La facilidad de formateo basada en esta biblioteca se propone para la estandarización en C ++ 20: P0645 .

Descargo de responsabilidad : soy el autor de {fmt}.

vitaut
fuente
¡Frio! ¿Viene también algo similar a sscanf?
ceztko
Muy posiblemente. Estamos investigando la posibilidad de reemplazar scanf.
vitaut
¡Excelente! También me pregunto si hay progreso hacia una versión local independiente y / o localizable seleccionable de std::to_string(). La página cppreference todavía está vinculada solo a std::to_chars(), que no es realmente lo que la gente necesita. Me pregunto si fmty / o c ++ 20 lidiar con él o no todavía.
ceztko
std::to_stringprobablemente permanecerá como está, pero le std::formatpermite controlar si usar la configuración regional o no (y de manera predeterminada no usa la configuración regional).
vitaut