Пробовал переносить 32-битный на 64-битный код. Мне было интересно, есть ли какие-то стандартные правила при переносе?
У меня своя компиляция кода в 64-битной среде, и теперь я сталкиваюсь с некоторыми ошибками, например
отсылать из указателя в целое число разного размера [-Werror = указатель-на-лить] для
x = (int32_t)y;
И для этого я использую x = (size_t) y; Я избавляюсь от ошибки, но это правильный путь. Кроме того, в разных местах мне нужно передать переменную в (unsigned long long). Например
printf("Total Time : %5qu\n",time->compile_time
Это дает ошибку: format '% qu' ожидает аргумент типа long long unsigned int, но аргумент 2 имеет тип (XYZ).
чтобы получить это исправлено, я делаю что-то вроде
printf("Total Time : %5qu\n",(unsigned long long) time->compile_time
Опять это правильно?
Я считаю безопасным предположить, что y
является указателем в этом случае.
Вместо size_t
вы должны использовать intptr_t
или uintptr_t
.
См. Size_t vs. uintptr_t.
Что касается вашего второго броска, это зависит от того, что вы подразумеваете под правильным?
Обычный совет - избегать кастинга. Однако, как и все в программировании, есть причина, по которой они доступны. При работе над реализацией malloc
во встроенной системе мне приходилось uintptr_t
указатели на uintptr_t
, чтобы иметь возможность выполнить необходимую арифметику. Этот код был протестирован на 64-битном ПК, но работал на 32-битном микроконтроллере. Тот факт, что я использовал две архитектуры, был лучшим способом обеспечить его портативный код.
Кастинг, хотя делает ваш код зависимым от того, как определяется базовый тип! Так же, как вы заметили с помощью x = (int32_t)y
эта строка сделала ваш код зависимым от того, что указатель имел ширину 32 бит.
Единственный совет, который я могу вам дать, - это знать свои типы. Если вы хотите бросить, это нормально (до тех пор, пока вы не можете сделать свою переменную с правильным типом), но это может снизить вашу переносимость, если вы не выбрали "правильный" тип, который нужно выполнить.
То же самое относится к printf
. Если бы я был вами, я сначала прочитал бы определение %5qu
сначала (это может помочь). Затем я попытаюсь использовать соответствующую типизированную переменную (или, наоборот, другую строку формата), и только если это не сработало, я бы прибегнул к актерскому составу.
Я никогда не использовал %qu
но я бы интерпретировал его как 64-битное беззнаковое int, поэтому я бы попытался использовать uint64_t
(потому что long long
не гарантировалось, что на всех платформах должно быть 64 бита). Хотя по тому, что я читал в Википедии, спецификатор q
имеет специфическую платформу для начала, поэтому было бы разумно изменить его.
Не более того, и вопрос становится слишком широким (хорошо, что мы придерживались конкретных примеров). Если вы застряли, вернитесь с отдельными типами, которые вы хотите проверить и задавать вопросы только о них.
Было ли это, что Страуструп сказал, что они называют его "броском", потому что он воспитывает то, что сломалось? ;-)
x = (int32_t) y;
В этом случае вы используете точный тип ширины, так что это действительно зависит от того, что такое x и y. Сообщение об ошибке предполагает, что y является указателем. Указатель не является int32_t, поэтому реальный вопрос заключается в том, почему y присваивается x... это может указывать на потенциальную проблему. Отбросить его можно просто покрыть проблему, чтобы она кусала вас во время выполнения, а не во время компиляции. Выясните, что код думает, что он делает, и "передислоцировать" типы, соответствующие этому коду. Причина, по которой ошибка уходит при использовании (size_t), заключается в том, что, вероятно, указатель имеет 64 бита, а size_t - 64 бита, но вы можете считать, что простая форма случайного каста удачи. То же самое верно при кастинге (без знака длинный). Не предполагайте, что int 32 или 64 бита и не используют литье в качестве инструмента портирования... это вызовет у вас проблемы. Трудно быть более конкретным на основе одной строки кода. Если вы хотите опубликовать функцию <25 строк, которая имеет проблемы; более конкретные рекомендации могут быть доступны.
intptr_t
илиuintptr_t
вместоsize_t
.x
иy
?