2010-07-02 2 views
81

У меня есть следующиеспецификаторы формата Printf для uint32_t и size_t

size_t i = 0; 
uint32_t k = 0; 

printf("i [ %lu ] k [ %u ]\n", i, k); 

я получаю следующее предупреждение при компиляции:

format ‘%lu’ expects type ‘long unsigned int’, but argument has type ‘uint32_t’ 

Когда я побежал это с помощью щепу я получил следующее:

Format argument 1 to printf (%u) expects unsigned int gets size_t: k 

благодарит за любые замечания,

+1

C89 не поддерживает 'uint32_t' из' 'или' '; если вы хотите использовать эти типы, вам следует перейти на C89. Как расширение, вполне вероятно, что GCC позволяет вам использовать их, но C89 не имеет такой поддержки. –

+9

И официальным модификатором формата C99 для 'size_t' является 'z', как в' '% zu''. –

+1

http://stackoverflow.com/questions/1401526/how-to-use-printf-to-display-off-t-nlink-t-size-t-and-other-special-types –

ответ

18

Похоже, вы ожидаете, что size_t будет таким же, как unsigned long (возможно, 64 бит), когда это фактически unsigned int (32 бит). Попробуйте использовать %zu в обоих случаях.

Я не совсем уверен, хотя.

+1

Предупреждений при компиляции.Однако при запуске splint я получаю следующее: 1) printf (% u) ожидает, что unsigned int получит uint32_t: i 2) printf (% u) ожидает, что unsigned int получит size_t: k – ant2009

+0

Похоже, что шина просто педантична. Вероятно, это исключает имена типов в исходном коде и не понимает, что они эквивалентны. Интересно, что он будет делать с ответом @ KennyTM ... Это, безусловно, должно быть более портативным. – Cogwheel

+3

шина на самом деле правильная вещь. Просто потому, что 'int32_t' оказывается' int' на вашем компиляторе/платформе, не означает, что он не может быть 'long' на другом. То же самое для 'size_t'. Это на самом деле выходит из своего пути и делает больше ** работы, чтобы обнаружить эту ошибку переносимости, поскольку простой, естественный чек должен был бы просто соблюдать typedef, как это делает компилятор. –

114

Попытка

#include <inttypes.h> 
... 

printf("i [ %zu ] k [ %"PRIu32" ]\n", i, k); 

z представляет собой целое число от длины же, как size_t и PRIu32 макро, defined in the C99 header inttypes.h, представляет беззнаковое 32-разрядное целое число.

+0

Компиляция без предупреждений. Но шине не нравится. Код нераспознанного формата:% zu. А для второго. Ошибка анализа. (Для справки об ошибках разбора см. Splits -help parseerrors.) *** Невозможно продолжить. – ant2009

+3

@robUK: Хех. Я предлагаю вам указать ошибку для шины. – kennytm

+6

Это правильный ответ. Хотя моя личная рекомендация - просто бросить, например. 'printf ("% lu ", (unsigned long) i)'. В противном случае позже вы получите кучу предупреждений по всему коду из-за изменения типа. – Dummy00001

16

Если вы не хотите использовать ПОИ * макросы, другой подход для печати ANY целочисленного типа является приведение к intmax_t или uintmax_t и использовать "%jd" или %ju, соответственно. Это особенно полезно для типов POSIX (или других ОС), для которых не определены макросы PRI *, например off_t.

21

Все, что необходимо, так это то, что спецификаторы формата и типы согласуются, и вы всегда можете сделать это, чтобы сделать это истинным. long составляет по меньшей мере 32 бита, поэтому %lu вместе с (unsigned long)k всегда корректно:

uint32_t k; 
printf("%lu\n", (unsigned long)k); 

size_t сложнее, поэтому %zu был добавлен в C99. Если вы не можете использовать это, то обрабатывайте его точно так же, как k (long - самый большой тип в C89, size_t вряд ли будет больше).

size_t sz; 
printf("%zu\n", sz); /* C99 version */ 
printf("%lu\n", (unsigned long)sz); /* common C89 version */ 

Если вы не получаете спецификаторы формата соответствует типу вы передаете, то printf будет делать эквивалент чтения слишком много или слишком мало памяти из массива. Пока вы используете явные приемы для соответствия типам, они переносимы.

Смежные вопросы