Как распечатать uint64_t? Сбой: «ложный трейлинг«% »в формате»

133

Я написал очень простой тестовый код printf uint64_t:

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

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

Я использую ubuntu 11.10 (64 бит) и gcc версии 4.6.1 для его компиляции, но не смог:

main.cpp: In function int main()’:
main.cpp:9:30: error: expected ‘)’ before PRIu64
main.cpp:9:47: warning: spurious trailing ‘%’ in format [-Wformat]
Дэн
источник
1
Кажется, что вы компилируете код C как C ++, это ваша ошибка. Если вы переименуете свой файл main.cи скомпилируете его с помощью gcc, все должно работать нормально.
Йенс Густедт
То же без ошибок: stackoverflow.com/questions/9225567/…
Чиро Сантилли 郝海东 冠状 病 六四 事件 法轮功
Для gcc или clang рекомендуется указать -std=c11версию используемого стандарта. Это отлавливает эту и другие ошибки. Я также рекомендую -Wall -Wextra -Wpedantic -Wconversionпо крайней мере.
Дэвислор

Ответы:

164

Стандарт ISO C99 указывает, что эти макросы должны быть определены только в случае явного запроса.

#define __STDC_FORMAT_MACROS
#include <inttypes.h>

... now PRIu64 will work
Будет
источник
@Dan, не забудьте отметить ответ как принятый (щелкните изображение галочки слева), если он решил вашу проблему.
zneak
9
Хм, достаточно просто включить заголовок. __STDC_FORMAT_MACROSМакросов требуется только для включения в C ++.
Йенс Густедт
15
@Jens: Действительно; __STDC_FORMAT_MACROSпоявляется только в сноске в C99, предполагая, что C ++ определяет эти макросы только при наличии запроса. Однако комитет C ++ решил проигнорировать это предложение: например, в черновике n3242, 27.9.2 / 3: Примечание: макросы, определенные в <cinttypes>, предоставляются безоговорочно. В частности, символ __STDC_FORMAT_MACROS, упомянутый в сноске 182 стандарта C, не играет никакой роли в C ++. Поэтому, когда компиляторы наверстают упущенное, нам не понадобится __STDC_FORMAT_MACROSни C, ни C ++.
Джон Маршалл
3
@John Marshall g ++ 4.7.3, похоже, требует макрос, даже если включен <inttypes.h>.
crockeea
4
@Eric: Очевидно, g ++ 4.7.3 не догнал! На самом деле, вероятно, вы используете его с версией glibc, предшествующей этому исправлению . Как обсуждалось в этом отчете glibc, libstdc ++ вашего g ++ 4.7.3 имеет код для решения этой проблемы. Если вы компилируете -std=c++0xи, возможно, #include <cinttypes>, а не <inttypes.h>, я считаю, что он предоставит макросы формата без вашего предложения __STDC_FORMAT_MACROS.
Джон Маршалл
4

При компиляции memcached под Centos 5.xi возникла та же проблема.

Решение - обновить gcc и g ++ как минимум до версии 4.4.

Перед компиляцией убедитесь, что ваш CC / CXX установлен (экспортирован) в правые двоичные файлы.

Андерс Элиассон
источник
1

Поскольку вы включили тег C ++, вы можете использовать библиотеку {fmt} и вообще избежать PRIu64макросов и других printfпроблем:

#include <fmt/core.h>

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

Средство форматирования, основанное на этой библиотеке, предлагается для стандартизации в C ++ 20: P0645 .

Отказ от ответственности : я автор {fmt}.

Витовт
источник
Прохладно! Это тоже что-то похожее sscanf?
ceztko
Вполне возможно. Мы изучаем возможность замены scanf.
Витаут
Большой! Также мне интересно, есть ли прогресс в направлении независимой от локали и / или локализуемой версии std::to_string(). Страница cppreference по-прежнему ссылается только на то std::to_chars(), что не совсем то, что нужно людям. Интересно, fmtи / или C ++ 20 справиться с этим или нет.
ceztko
std::to_stringвероятно, останется как есть, но std::formatпозволит вам контролировать, использовать языковой стандарт или нет (и по умолчанию он не использует языковой стандарт).
vitaut