То, как я должен обработать “бросок от ‘пустого*’ к 'интервалу', теряет точность” при компиляции 32-битного кода на 64-разрядной машине?

У меня есть пакет, который компилирует и хорошо работает на 32-разрядной машине. Я теперь пытаюсь заставить это компилировать на 64-разрядной машине и находить следующую ошибку -

 error: cast from ‘void*’ to ‘int’ loses precision

Существует ли флаг компилятора для подавления этих ошибок? или я должен вручную отредактировать эти файлы для ухода от этих бросков?

32
задан jalf 8 January 2010 в 03:17
поделиться

9 ответов

Ваш код взломан. От игнорирования предупреждений, которые выдает компилятор, он не станет меньше ломаться.

Как вы думаете, что произойдет, если вы попытаетесь сохранить 64-битный указатель в 32-битное целое число? Половина ваших данных будет выброшена. Я не могу вообразить много случаев, когда это правильно или когда это не вызовет ошибок.

Исправьте свой код. Или оставайтесь на 32-битной платформе, на которой в настоящее время работает код.

Если ваш компилятор определяет intptr_t или uintptr_t , используйте их, поскольку они являются целочисленными типами, размер которых гарантированно достаточно велик для хранения указателя.

Если эти типы недоступны, size_t или ptrdiff_t также достаточно велики, чтобы содержать указатель на на большинстве (не на всех) платформах. Или используйте long (обычно 64-битный на 64-битных платформах в компиляторе GCC) или long long (типы C99, которые большинство, но не все компиляторы, поддерживают в C ++) или какой-либо другой интегральный тип, определяемый реализацией, который имеет ширину не менее 64 бит на 64-битной платформе.

23
ответ дан 27 November 2019 в 19:45
поделиться

Проблема в том, что в 32-битном формате int (32-битное целое число) будет храниться значение указателя.

Когда вы переходите на 64-битный, вы больше не можете хранить указатель в int - он недостаточно велик, чтобы содержать 64-битный указатель. Для этого предназначен тип intptr_t .

50
ответ дан 27 November 2019 в 19:45
поделиться

Это ошибка не просто так: int только наполовину больше void* на вашей машине, поэтому вы не можете просто сохранить void* в int. Вы потеряете половину указателя, а когда программа позже снова попытается вытащить указатель из этой int, она не получит ничего полезного.

Даже если компилятор не выдаст ошибку, код, скорее всего, не будет работать. Код необходимо изменить и просмотреть на 64-битную совместимость.

11
ответ дан 27 November 2019 в 19:45
поделиться

С точки зрения портативности литье указателя на интригу ужасно. Размер int определяется смесью компилятора и архитектуры. Поэтому был создан заголовок stdint.h, позволяющий явно указывать размер используемого типа на множестве различных платформ с различными размерами слов.

Лучше всего приведение к uintptr_t или intptr_t (из stdint.h, и выбрать тот, который наилучшим образом соответствует нужному знаку).

7
ответ дан 27 November 2019 в 19:45
поделиться

Для лучшей переносимости можно попробовать использовать intptr_t вместо int, где требуется каста указателей, например, обратные вызовы.

4
ответ дан 27 November 2019 в 19:45
поделиться

Вы не хотите подавлять эти ошибки, так как, скорее всего, они указывают на проблему с логикой кода.

Если вы подавите ошибки, это может даже сработать некоторое время. В то время как указатель указывает на адрес в первых 4 Гб, верхние 32 бита будут равны 0 и вы не потеряете никаких данных. Но как только вы получите адрес > 4 Гб, ваш код начнет "таинственно" не работать.

Необходимо модифицировать любой int, который может содержать указатель на intptr_t.

4
ответ дан 27 November 2019 в 19:45
поделиться

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

3
ответ дан 27 November 2019 в 19:45
поделиться

Подавление предупреждений - плохая идея, но может быть флаг компилятора для использования 64-битных целых чисел, в зависимости от вашего компилятора и архитектуры, и это безопасный способ решить проблему (при условии, что конечно, код также не предполагал, что целые числа являются 32-битными). Для gcc флаг -m64.

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

2
ответ дан 27 November 2019 в 19:45
поделиться

Как определено текущим стандартом C ++, нет целого типа, который гарантированно удерживает указатель. Некоторые платформы будут иметь INTPTR_T, но это не стандартная особенность C ++. Принципиально лечение битов указателя, как если бы они были целым числом, не является портативной вещью (хотя его можно сделать для работы на многих платформах).

Если причина отличия заключается в том, чтобы сделать указатель непрозрачной, то пустота * уже достигает этого, поэтому код может использовать void * вместо INT. TypEDEF может сделать это немного приятнее в коде

typedef void * handle_t;

, если причина для активов состоит в том, чтобы сделать арифметику указателя с гранулярностью байта, то наилучший способ, вероятно, отбрасывается до A (Char Const *) и сделать математику с этим Отказ

Если причина для активов состоит в том, чтобы добиться совместимости с какой-то существующей библиотекой (возможно, более старый интерфейс обратного вызова), который не может быть изменен, то я думаю, что вам нужно просмотреть документацию для этой библиотеки. Если библиотека способна поддерживать функциональность, которые вам требуют (даже на 64-битной платформе), то его документация может обратиться к предполагаемому решению.

2
ответ дан 27 November 2019 в 19:45
поделиться
Другие вопросы по тегам:

Похожие вопросы: