Jak wydrukować uint64_t? Niepowodzenie z: „fałszywe końcowe„% ”w formacie”

133

Napisałem bardzo prosty kod testowy printf uint64_t:

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

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

Do kompilacji używam ubuntu 11.10 (64-bitowego) i gcc w wersji 4.6.1, ale nie powiodło się:

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
źródło
1
Wygląda na to, że kompilujesz kod w C jako C ++, to jest twój błąd. Jeśli zmienisz nazwę pliku na main.ci skompilujesz go za pomocą gcc, wszystko powinno działać dobrze.
Jens Gustedt
To samo bez błędów: stackoverflow.com/questions/9225567/…
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
W przypadku gcc lub clang dobrym pomysłem jest określenie -std=c11lub wersja używanego standardu. To wyłapuje ten i inne błędy. Ja też -Wall -Wextra -Wpedantic -Wconversionprzynajmniej polecam .
Davislor,

Odpowiedzi:

164

Norma ISO C99 określa, że ​​te makra muszą być definiowane tylko na wyraźne żądanie.

#define __STDC_FORMAT_MACROS
#include <inttypes.h>

... now PRIu64 will work
Będzie
źródło
@Dan, nie zapomnij oznaczyć odpowiedzi jako zaakceptowanej (kliknij obraz znacznika wyboru po lewej stronie), jeśli to rozwiązało Twój problem.
zneak
9
Hm, samo dołączenie nagłówka powinno wystarczyć. __STDC_FORMAT_MACROSMakro jest wymagane tylko w przypadku włączenia w C ++.
Jens Gustedt
15
@Jens: Rzeczywiście; __STDC_FORMAT_MACROSpojawia się tylko w przypisie w C99, co sugeruje, że C ++ definiuje te makra tylko w obecności żądania. Jednak komisja C ++ zdecydowała się zignorować sugestię: np. W wersji roboczej n3242, 27.9.2 / 3: Uwaga: makra zdefiniowane przez <cinttypes> są dostarczane bezwarunkowo. W szczególności symbol __STDC_FORMAT_MACROS, o którym mowa w przypisie 182 normy C, nie odgrywa żadnej roli w C ++. Więc kiedy kompilatory nadrobią zaległości, nie będziemy potrzebować __STDC_FORMAT_MACROSani C, ani C ++.
John Marshall
3
@John Marshall g ++ 4.7.3 wydaje się wymagać makra, nawet jeśli zawiera <inttypes.h>.
crockeea
4
@Eric: Najwyraźniej g ++ 4.7.3 nie dogonił! W rzeczywistości prawdopodobnie używasz go z wersją glibc, która jest starsza niż ta poprawka błędu . Jak omówiono w raporcie glibc, libstdc ++ twojego g ++ 4.7.3 zawiera kod pozwalający obejść ten problem. Jeśli kompilujesz z -std=c++0x<cinttypes> i być może #include zamiast <inttypes.h>, uważam, że zapewniłoby to makra formatu bez konieczności dostarczania __STDC_FORMAT_MACROS.
John Marshall
4

Podczas kompilacji memcached pod Centos 5.xi napotkałem ten sam problem.

Rozwiązaniem jest aktualizacja gcc i g ++ przynajmniej do wersji 4.4.

Upewnij się, że plik CC / CXX jest ustawiony (wyeksportowany) do odpowiednich plików binarnych przed kompilacją.

Anders Eliasson
źródło
1

Ponieważ dołączyłeś tag C ++, możesz użyć biblioteki {fmt} i całkowicie uniknąć PRIu64makra i innych printfproblemów:

#include <fmt/core.h>

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

Narzędzie formatowania oparte na tej bibliotece jest proponowane do standaryzacji w C ++ 20: P0645 .

Zastrzeżenie : jestem autorem {fmt}.

vitaut
źródło
Chłodny! Czy nadchodzi też coś podobnego sscanf?
ceztko
Całkiem możliwe. Badamy możliwość wymiany scanf.
vitaut
Wspaniały! Zastanawiam się również, czy jest postęp w kierunku wersji niezależnej od ustawień regionalnych i / lub wybieralnych ustawień regionalnych std::to_string(). Strona cppreference nadal zawiera tylko linki std::to_chars(), które nie są tak naprawdę tym, czego ludzie potrzebują. Zastanawiam się, czy fmti / lub c ++ 20 sobie z tym poradzą, czy jeszcze nie.
ceztko
std::to_stringprawdopodobnie pozostanie bez zmian, ale std::formatpozwala kontrolować, czy używać ustawień regionalnych, czy nie (i domyślnie nie używa ustawień regionalnych).
vitaut