Подтвердить что ты не робот

Printf с sizeof на платформах 32 и 64: как обрабатывать формат кода в независимой платформе?

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

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 бит. Но я бы предпочел иметь код, который работает на обоих, вместо того, чтобы просто конвертировать назад и вперед.

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

4b9b3361

Ответ 1

Идентификаторы переносимых принтеров содержатся в файле include inttypes.h.

Этот файл включает много переносных идентификаторов для вашей конкретной среды выполнения. Для вашего примера вы хотите PRIuPTR, что означает " PR intf I dentifier 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.

Ответ 2

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

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

Ответ 3

Прежде всего, вы должны сопоставить спецификатор "%" с фактическим типом данных, который вы хотите распечатать. sizeof возвращает тип данных size_t, и так же, как вы не должны пытаться распечатать float с помощью спецификатора "% 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 шире, чем длинный, но я не знаю никаких таких систем, и я даже не уверен, разрешает ли это стандарт.