Как решить: предупреждение "приведение к указателю из целого числа разного размера" в коде 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();

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


есть два варианта:

  1. func бросает фактический указатель на целое число; позже он используется в качестве указателя.
  2. 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 Преобразование Макросов для обсуждения вопроса.