Як printf 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, все має працювати добре.
Єнс Гуведт


За допомогою 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: Мабуть, г ++ 4.7.3 не наздогнали! Насправді, ймовірно, ви використовуєте його з версією glibc, яка передувала цьому виправленню помилок . Як було обговорено у цьому звіті про glibc, у вашому g ++ 4.7.3 в libstdc ++ є код, який дозволяє вирішити цю проблему. Якщо ви компілюєте з, -std=c++0xможливо, #include <cinttypes>, а не <inttypes.h>, я вважаю, що він надасть формат макросів без надання вами __STDC_FORMAT_MACROS.
Джон Маршалл

4

Під час компілювання пам’яті під 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.
vitaut

Чудово! Також мені цікаво, чи є прогрес у створенні незалежної та / або версії, що вибирається з мови std::to_string(). Сторінка cppreference як і раніше посилається лише на те std::to_chars(), що насправді не те, що потрібно людям. Цікаво, чи fmtта / або c ++ 20 займаються цим чи ні ще.
ceztko

std::to_stringймовірно, залишиться таким, як є, але std::formatдозволяє вам контролювати, використовувати або не використовувати локаль (і за замовчуванням він не використовує локаль).
vitaut
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.