Общеизвестно, что для печати значений переменных, тип которых является одним из целочисленных типов с фиксированной шириной (например, uint32_t
), вам необходимо включить заголовочный файл cinttypes
(в C++) или inttypes.h
(в C) и использовать макросы спецификаторов формата, такие как PRIu32
. Но как сделать то же самое при использовании функции wprintf
? В этом случае такой макрос должен раскрываться как строковый литерал с префиксом L
.
Как распечатать значение переменных uint32_t через функцию wprintf?
Ответы (4)
Будет ли это работать или нет, на самом деле зависит от того, какой стандарт C использует компилятор.
Из этой ссылки на строковый литерал
Можно конкатенировать только два узких или два широких строковых литерала. (до C99)
а также
Если один литерал не имеет префикса, результирующий строковый литерал имеет ширину/кодировку, указанные литералом с префиксом. Если два строковых литерала имеют разные префиксы кодирования, конкатенация определяется реализацией. (начиная с C99)
[Выделено мое]
Поэтому, если вы используете старый компилятор или тот, который не поддерживает стандарт C99 (или более позднюю версию), это невозможно. Кроме того, целочисленные типы с фиксированной шириной были стандартизированы в C99, поэтому макросы на самом деле не существуют для таких старых компиляторов, что делает вопрос спорным.
Для более современных компиляторов, поддерживающих C99 и более поздние версии, это не проблема, поскольку конкатенация строковых литералов будет работать, и компилятор превратит строку без префикса в строку широких символов, поэтому, например,
wprintf(L"Value = %" PRIu32 "\n", uint32_t_value);
будет работать нормально.
Если у вас есть компилятор до C99, но все еще есть макросы и целые типы с фиксированной шириной, вы можете использовать макросы, подобные функциям, для добавления префикса L
перед строковыми литералами. Что-то типа
#define LL(s) L ## s
#define L(s) LL(s)
...
wprintf(L"Value = %" L(PRIu32) L"\n", uint32_t_value);
#undef PRIu32
, а затем #define PRIu32 L"u"
. Тогда wprintf(L"Value = %" PRIu32 "\n", uint32_t_value);
должен работать со старыми компиляторами, по крайней мере, с моей старой Visual Studio 6.
- person Jabberwocky; 29.04.2016
PRIu32
?
- person Constructor; 29.04.2016
Не уверен, в чем проблема, но здесь (VS 2015) оба
wprintf(L"AA %" PRIu32 L" BB", 123);
а также
printf("AA %" PRIu32 " BB", 123);
скомпилировать правильно и дать следующий вывод:
AA 123 BB
Даже если ваш компилятор не поддерживает конкатенацию литералов с разными префиксами, вы всегда можете расширить узкий:
#define WIDE(X) WIDE2(X)
#define WIDE2(X) L##X
wprintf(L"%" WIDE(PRIu32), foo);
(Более слабая) альтернатива использованию макросов из <inttypes.h>
заключается в преобразовании/приведении типа фиксированной ширины к эквивалентному или большему стандартному типу.
wprintf(L"%lu\n", 0ul + some_uint32_t_value);
// or
wprintf(L"%lu\n", (unsigned long) some_uint32_t_value);
wprintf
что-то другое, чем вы ожидаете? - person Jabberwocky   schedule 29.04.2016printf()
не так распространено в программах c++, используйте<iostream>
, и он со всем этим справляется. - person Iharob Al Asimi   schedule 29.04.2016wprintf
принимает только строку широких символов в качестве строки формата. - person Constructor   schedule 29.04.2016printf
не так уж часто используется в C++, но в некоторых случаях это может быть полезно. - person Constructor   schedule 29.04.2016PRIu32
. - person cremno   schedule 29.04.2016