printf с sizeof на 32 против 64 платформ: как мне обрабатывать код формата независимо от платформы - PullRequest
29 голосов
/ 10 сентября 2009

У меня есть некоторый код, который печатает объем памяти, используемый программой. Линия похожа на это:

printf("The about of RAM used is %u", anIntVariable*sizeof(double) );

где anIntVariable - это переменная типа int для числа элементов двойного массива. В любом случае, в 32-разрядных системах у меня никогда не возникало проблем, но в 64-разрядных системах я получаю предупреждение компилятора об использовании "% u" для длинного целого без знака. Использование «% lu» в качестве кода формата устраняет проблему на 64-битной платформе, но заставляет компилятор жаловаться на 32-битную версию, поскольку тип возвращается к unsigned int. Я обнаружил, что действительно sizeof (double) возвращает другое значение в 32-х и 64-х битных системах. Я нашел несколько руководств для веб-страниц, конвертирующих код из 32-битных в 64-битные. Но я бы предпочел иметь код, который работает на обоих, а не просто конвертировать туда и обратно.

Как мне написать эту строку независимо от платформы? Я знаю много способов, которыми я мог бы сделать это, используя директивы препроцессора, но это похоже на хак. Конечно, есть элегантный способ, который я не понимаю.

Ответы [ 3 ]

20 голосов
/ 10 сентября 2009

Переносимые идентификаторы printf предоставляются во включаемом файле inttypes.h.

Этот включаемый файл имеет много переносимых идентификаторов для вашей конкретной среды выполнения. Для вашего примера вы хотите PRIuPTR, что означает « PR intf I средство для удаления u nsigned с размером до размера указателя".

Ваш пример будет:

printf("The amount of RAM used is %" PRIuPTR, anIntVariable*sizeof(double) );

Результаты для 64-битного Linux с GCC 4.3 (int anIntVariable = 1):

$ gcc test.c -m32 -o test && ./test
The amount of RAM used is 8
$ gcc test.c -o test && ./test
The amount of RAM used is 8

Для полноты картины также есть идентификаторы для scanf, префиксы которых - SCN.

13 голосов
/ 11 сентября 2009

Возвращаемое значение sizeof - size_t. Если вы используете компилятор, совместимый с C99, похоже, вы можете использовать для этого %zd%zu.

D'Oh: %zu (без знака), конечно. Спасибо, только.

7 голосов
/ 11 сентября 2009

Прежде всего, вы должны сопоставить спецификатор "%" с фактическим типом данных, который вы хотите напечатать. sizeof возвращает тип данных size_t , и точно так же, как вы не должны пытаться печатать с плавающей точкой, используя спецификатор "% d", вы не должны пытаться печатать size_t с помощью " % u "или"% d "или все, что на самом деле не означает size_t.

Другие ответы дали несколько хороших способов справиться с этим с помощью новых компиляторов ("% z" и PRIu32), но способ, которым мы привыкли это делать, - просто привести size_t к unsigned long, а затем распечатать его с помощью " % лу ":

printf("The amount of RAM used is %lu", (unsigned long)(anIntVariable*sizeof(double)) );

Это не будет работать в системах, где size_t шире, чем long, но я не знаю ни одной из таких систем, и я даже не уверен, позволяет ли это стандарт.

...