Известно, что для печати значений переменных, которые являются типом целочисленных типов фиксированной ширины (например, uint32_t
), вам необходимо включить cinttypes
(в C++) или inttypes.h
(в C) заголовочный файл и использовать спецификаторы формата макросы, такие как PRIu32
. Но как сделать то же самое, когда используется функция wprintf
? В этом случае такой макрос должен расширяться как строковый литерал с префиксом L
.Как напечатать значение переменной uint32_t через функцию wprintf?
ответ
Если это будет работать или не зависит от того, какой стандарт C используется компилятором.
От this string literal reference
только две узкие или две широкие строковые литералы могут быть соединены. (до C99)
и
Если один литерал без префикса, в результате строка символов не имеет ширину/кодирования, указанного префикса буквально. Если два строковых литерала имеют разные префиксы кодирования, конкатенация определяется реализацией. (так C99)
[выделено мной]
Так что, если вы используете старый компилятор или тот, который не поддерживает стандарт C99 (или позже), это не представляется возможным. Кроме fixed-width integer types был стандартизирован в 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);
Благодарим вас за ответ. Вы правы, я использую старый компилятор, и это проблема с ним. – Constructor
Есть ли какое-либо решение для компиляторов, совместимых с C89? – Constructor
@Constructor Должно быть возможно использование некоторых макросов типа функции. Обновлен мой ответ. –
Не знаете, где проблема, но здесь (VS 2015) и
wprintf(L"AA %" PRIu32 L" BB", 123);
и
printf("AA %" PRIu32 " BB", 123);
компилировать правильно и дать следующий вывод:
AA 123 BB
Код, который компилируется одним компилятором, не является обязательным стандартным. – Constructor
@ Конструктор Я никогда не утверждал этого. –
Даже если ваш компилятор не поддерживает co ncatenation по-разному с префиксом литералов, всегда можно расширить узкий один:
#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);
В каких из C и C++ вы программируете? Выберите не более одного. – fuz
@FUZxxl Почему я должен выбрать только один? – Constructor
В чем проблема? Не компилируется ли ваш код? Отображает ли 'wprintf' что-то еще, чем вы ожидаете? –