Как решить: предупреждение "приведение к указателю из целого числа разного размера" в коде C?
Я удаляю предупреждения gcc из устаревшего кода.
можно ли подавить предупреждение "приведение к указателю из целого числа разного размера" посредством типизации:
example:
some_struct *ptr = func() // func() returns an integer.
может ли кто-нибудь помочь мне решить такие предупреждения gcc?
3 ответов
во-первых, если вы можете исправить func
(разрешено изменять его источник), затем исправить его. Если его вычисления можно выполнить с помощью указателей, то делайте их с помощью указателей и указателей возврата. Иногда есть веские причины для работы с адресами в виде целых чисел (например, решение проблем выравнивания в специальном коде). В таком случае измените func
использовать uintptr_t
тип (определенный в stdint.h
). Он предназначен для обработки указателей как целых чисел, когда это необходимо. (Существует также intptr_t
если подписан арифметика лучше почему-то, но я вообще нахожу неподписанное uintptr_t
будет менее хлопотно.) Желательно, func
преобразовать uintptr_t
к указателю при его возврате, поэтому возвращаемый тип func
будет указатель (на что-то, возможно,some_struct
или void
).
если вы не можете исправить func
, затем вы можете использовать приведения, чтобы сообщить компилятору, что вы намерены выполнить преобразования, которые выполняются. Однако это конкретное сообщение об ошибке говорит вам, что вы не просто преобразование целого числа в указатель, но вы преобразуете целое число одного размера (например, четыре байта) в указатель другого размера (например, восемь байтов). Вероятно, этот код был первоначально написан для системы, где целочисленный тип возвращен func
имел тот же размер, что и тип указателя, но теперь вы компилируете в системе, где тип указателя больше или меньше этого целочисленного размера.
в этом случае, вы должны убедиться, что расчет производится по func
работает в новой архитектуре. Если он возвращает только 32-разрядное значение, будет ли оно всегда содержать правильное значение? То есть, ничего не будет потеряно из-за недостающих высоких 32 бит? Нет адреса, что func
должны посчитать не превышает максимальное значение типа integer он использует? Если func
использует целочисленные типы со знаком, также рассмотрим бит знака.
если вы гарантировали, что значение, возвращаемое func
правильно, тогда вы можете использовать явные приведения, такие как: some_struct *ptr = (some_struct *) (intptr_t) func();
.
мой gcc не дает предупреждение, которое вы процитировали. Это также было бы странно, потому что в вашем коде нет приведения.
Я получаю предупреждение
assignment makes pointer from integer without a cast
обратите внимание на часть "без приведения". Таким образом, вы можете заставить gcc молчать, бросая (без изменения поведения):
some_struct *ptr = (void*)func();
затем вы получите предупреждение ("приведение к указателю из целого числа разного размера"), если тип возврата func
не подходит для адресов. Это может быть отключено дополнительно кастинг func()
к соответствующему целочисленному типу, например intptr_t
:
some_struct *ptr = (void*)(intptr_t)func();
все это в предположении, что вы действительно хотите преобразовать целое число неправильного размера в указатель. Возможно, доработка кода-лучшая идея.
есть два варианта:
-
func
бросает фактический указатель на целое число; позже он используется в качестве указателя. -
func
возвращает целое число, которое хранится в указателе;ptr
позже преобразован в целое и используется как целое.
в первом случае возвращаемое значение func
будет потерять информацию и, возможно, аварии или хуже, если int
меньше, чем размер указатель данных, который будет на most 64-разрядной модели памяти (включая Windows и Linux). В этом случае вы должны изменить тип возвращаемого func
до intptr_t
; см. использование intptr_t вместо void*? и почему / когда использовать 'intptr_t' для литья типов в C?.
во втором случае это менее проблема, но для решения проблем endianness вы должны бросить через intptr_t
: some_struct *ptr = (some_struct *)(intptr_t)func();
и позже int value = (int)(intptr_t)ptr;
. См.Тип GLib Преобразование Макросов для обсуждения вопроса.