Как можно распечатать size_t переменную портативно с помощью printf семейства?

У меня есть переменная типа size_t, и я хочу распечатать его использование printf(). Какой спецификатор формата я использую для печати его портативно?

В 32-разрядной машине, %u кажется правильным. Я скомпилировал с g++ -g -W -Wall -Werror -ansi -pedantic, и не было никакого предупреждения. Но когда я компилирую тот код в 64-разрядной машине, он производит предупреждение.

size_t x = <something>;
printf( "size = %u\n", x );

warning: format '%u' expects type 'unsigned int', 
    but argument 2 has type 'long unsigned int'

Предупреждение уходит, как ожидалось, если я изменяю это на %lu.

Вопрос, как я могу написать код, так, чтобы он скомпилировал предупреждение свободного и на 32-и на машины на 64-биты?

Править: Как обходное решение, я предполагаю, что один ответ мог бы быть должен "бросить" переменную в целое число, которое является достаточно большим, сказать unsigned long, и использование печати %lu. Это работало бы в обоих случаях. Я смотрю, если существует какая-либо другая идея.

371
задан Arun 30 January 2019 в 09:00
поделиться

8 ответов

Используйте модификатор z :

size_t x = ...;
ssize_t y = ...;
printf("%zu\n", x);  // prints as unsigned decimal
printf("%zx\n", x);  // prints as hex
printf("%zd\n", y);  // prints as signed decimal
450
ответ дан 23 November 2019 в 00:04
поделиться

Для C89 используйте % lu и приведите значение к unsigned long :

size_t foo;
...
printf("foo = %lu\n", (unsigned long) foo);

Для C99 и позже используйте % zu :

size_t foo;
...
printf("foo = %zu\n", foo);
58
ответ дан 23 November 2019 в 00:04
поделиться
std::size_t s = 1024;
std::cout << s; // or any other kind of stream like stringstream!
5
ответ дан 23 November 2019 в 00:04
поделиться

C99 определяет "% zd" и т. Д. для этого. (спасибо комментаторам) В C ++ нет переносимого спецификатора формата для этого - вы могли бы использовать % p , что слово woulkd в этих двух сценариях, но не переносимый вариант либо, и дает значение в шестнадцатеричном формате.

В качестве альтернативы можно использовать потоковую передачу (например, stringstream) или безопасную замену printf, например Boost Format . Я понимаю, что этот совет имеет ограниченное применение (и требует C ++). (Мы использовали аналогичный подход, подходящий для наших нужд, при реализации поддержки юникода.)

Основная проблема для C состоит в том, что printf с многоточием небезопасен по замыслу - он должен определять размер дополнительного аргумента из известных аргументов, так что это не может быть исправлено, чтобы поддерживать "все, что у вас есть". Так что, если ваш компилятор не реализует некоторые проприетарные расширения, вам не повезло.

-1
ответ дан 23 November 2019 в 00:04
поделиться

Похоже, это зависит от того, какой компилятор вы используете (blech):

... и, конечно, если вы используете C ++, вы можете использовать cout вместо , предложенного AraK .

83
ответ дан 23 November 2019 в 00:04
поделиться

Тем, кто говорит об этом на C ++, который не обязательно поддерживает расширения C99, я настоятельно рекомендую boost :: format. Это делает спорным вопрос о размере типа size_t:

std::cout << boost::format("Sizeof(Var) is %d\n") % sizeof(Var);

Поскольку вам не нужны спецификаторы размера в boost :: format, вы можете просто беспокоиться о том, как вы хотите отображать значение.

5
ответ дан 23 November 2019 в 00:04
поделиться

Будет ли он предупреждать вас, если вы передадите 32-битное целое число без знака в формат% lu? Это должно быть нормально, поскольку преобразование четко определено и не теряет никакой информации.

Я слышал, что некоторые платформы определяют макросы в , которые можно вставить в литерал строки формата, но я не вижу этого заголовка в моем компиляторе Windows C ++, что подразумевает его не может быть кроссплатформенным.

0
ответ дан 23 November 2019 в 00:04
поделиться
printf("size = %zu\n", sizeof(thing) );
5
ответ дан 23 November 2019 в 00:04
поделиться
Другие вопросы по тегам:

Похожие вопросы: