У меня есть пакет, который компилирует и хорошо работает на 32-разрядной машине. Я теперь пытаюсь заставить это компилировать на 64-разрядной машине и находить следующую ошибку -
error: cast from ‘void*’ to ‘int’ loses precision
Существует ли флаг компилятора для подавления этих ошибок? или я должен вручную отредактировать эти файлы для ухода от этих бросков?
Ваш код взломан. От игнорирования предупреждений, которые выдает компилятор, он не станет меньше ломаться.
Как вы думаете, что произойдет, если вы попытаетесь сохранить 64-битный указатель в 32-битное целое число? Половина ваших данных будет выброшена. Я не могу вообразить много случаев, когда это правильно или когда это не вызовет ошибок.
Исправьте свой код. Или оставайтесь на 32-битной платформе, на которой в настоящее время работает код.
Если ваш компилятор определяет intptr_t
или uintptr_t
, используйте их, поскольку они являются целочисленными типами, размер которых гарантированно достаточно велик для хранения указателя.
Если эти типы недоступны, size_t
или ptrdiff_t
также достаточно велики, чтобы содержать указатель на на большинстве (не на всех) платформах. Или используйте long
(обычно 64-битный на 64-битных платформах в компиляторе GCC) или long long
(типы C99, которые большинство, но не все компиляторы, поддерживают в C ++) или какой-либо другой интегральный тип, определяемый реализацией, который имеет ширину не менее 64 бит на 64-битной платформе.
Проблема в том, что в 32-битном формате int (32-битное целое число) будет храниться значение указателя.
Когда вы переходите на 64-битный, вы больше не можете хранить указатель в int - он недостаточно велик, чтобы содержать 64-битный указатель. Для этого предназначен тип intptr_t .
Это ошибка не просто так: int
только наполовину больше void*
на вашей машине, поэтому вы не можете просто сохранить void*
в int
. Вы потеряете половину указателя, а когда программа позже снова попытается вытащить указатель из этой int
, она не получит ничего полезного.
Даже если компилятор не выдаст ошибку, код, скорее всего, не будет работать. Код необходимо изменить и просмотреть на 64-битную совместимость.
С точки зрения портативности литье указателя на интригу ужасно. Размер int определяется смесью компилятора и архитектуры. Поэтому был создан заголовок stdint.h, позволяющий явно указывать размер используемого типа на множестве различных платформ с различными размерами слов.
Лучше всего приведение к uintptr_t или intptr_t (из stdint.h, и выбрать тот, который наилучшим образом соответствует нужному знаку).
Для лучшей переносимости можно попробовать использовать intptr_t
вместо int, где требуется каста указателей, например, обратные вызовы.
Вы не хотите подавлять эти ошибки, так как, скорее всего, они указывают на проблему с логикой кода.
Если вы подавите ошибки, это может даже сработать некоторое время. В то время как указатель указывает на адрес в первых 4 Гб, верхние 32 бита будут равны 0 и вы не потеряете никаких данных. Но как только вы получите адрес > 4 Гб, ваш код начнет "таинственно" не работать.
Необходимо модифицировать любой int, который может содержать указатель на intptr_t.
Вы должны вручную отредактировать эти файлы, чтобы заменить их кодом, который вряд ли будет содержать ошибки и будет непереносимым.
Подавление предупреждений - плохая идея, но может быть флаг компилятора для использования 64-битных целых чисел, в зависимости от вашего компилятора и архитектуры, и это безопасный способ решить проблему (при условии, что конечно, код также не предполагал, что целые числа являются 32-битными). Для gcc флаг -m64.
Я полагаю, что лучшим ответом по-прежнему является исправление кода, но если это устаревший сторонний код и эти предупреждения постоянно распространяются, я не могу рассматривать этот рефакторинг как очень эффективное использование вашего времени. Однако определенно не приводите указатели к целым числам ни в одном из ваших новых кодов.
Как определено текущим стандартом C ++, нет целого типа, который гарантированно удерживает указатель. Некоторые платформы будут иметь INTPTR_T, но это не стандартная особенность C ++. Принципиально лечение битов указателя, как если бы они были целым числом, не является портативной вещью (хотя его можно сделать для работы на многих платформах).
Если причина отличия заключается в том, чтобы сделать указатель непрозрачной, то пустота * уже достигает этого, поэтому код может использовать void * вместо INT. TypEDEF может сделать это немного приятнее в коде
typedef void * handle_t;
, если причина для активов состоит в том, чтобы сделать арифметику указателя с гранулярностью байта, то наилучший способ, вероятно, отбрасывается до A (Char Const *) и сделать математику с этим Отказ
Если причина для активов состоит в том, чтобы добиться совместимости с какой-то существующей библиотекой (возможно, более старый интерфейс обратного вызова), который не может быть изменен, то я думаю, что вам нужно просмотреть документацию для этой библиотеки. Если библиотека способна поддерживать функциональность, которые вам требуют (даже на 64-битной платформе), то его документация может обратиться к предполагаемому решению.