printf с sizeof на 32 против 64 платформ: как мне обрабатывать код формата независимо от платформы?
-
05-07-2019 - |
Вопрос
У меня есть код, который печатает объем памяти, используемый программой. Строка похожа на это:
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-битный. Но я бы предпочел иметь код, который работает на обоих, а не просто конвертировать туда и обратно.
Как мне написать эту строку независимо от платформы? Я знаю много способов, которыми я мог бы сделать это, используя директивы препроцессора, но это похоже на хак. Конечно, есть элегантный способ, который я не понимаю.
Решение
Переносимые идентификаторы printf предоставляются во включаемом файле inttypes.h
. р>
Этот включаемый файл имеет много переносимых идентификаторов для вашей конкретной среды выполнения. Для вашего примера вы хотите, чтобы PRIuPTR, что означает PR intf I средство для удаления u , было подписано размером до размера указателя ". р>
Ваш пример будет таким:
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.
Другие советы
Возвращаемое значение sizeof - size_t. Если вы используете компилятор, совместимый с C99, похоже, что для этого вы можете использовать % zd
% zu
.
D'oh: % zu
(без знака), конечно. Спасибо, только.
Прежде всего, вы должны соответствовать значению "% " спецификатор с фактическим типом данных, который вы хотите напечатать. sizeof возвращает тип данных size_t , и точно так же, как вы не должны пытаться печатать с плавающей точкой, используя "% d " спецификатор, вы не должны пытаться напечатать size_t с "% u " или "% d" или что-нибудь, что на самом деле не означает size_t.
Другие ответы дали несколько хороших способов справиться с этим с помощью новых компиляторов ("% z " и PRIu32), но способ, которым мы привыкли это делать, заключался в простом приведении size_t к unsigned long, а затем распечатке его с использованием & Quot;% лу & Quot; р>
printf("The amount of RAM used is %lu", (unsigned long)(anIntVariable*sizeof(double)) );
Это не будет работать в системах, где size_t шире, чем long, но я не знаю ни одной из таких систем, и я даже не уверен, позволяет ли это стандарт.