2012-08-03 17 views
10

Estoy eliminando las advertencias de gcc de un código heredado.Cómo resolver: advertencia de "enviar al puntero desde el entero de diferentes tamaños" en el código C?

¿Es posible suprimir la advertencia "echar a un puntero desde un entero de tamaño diferente" a través de encasillamiento:

example: 

some_struct *ptr = func() // func() returns an integer. 

Puede alguien por favor me guía de cómo resolver este tipo de advertencias gcc?

+7

¿Por qué le gustaría colocar un entero en un puntero de estructura? – Jay

+0

Es posible, pero los casos en que esa es la forma correcta de hacerlo son raros. –

+0

¿hay sobrecarga de las diferencias de "salida"? (No los parámetros de entrada) –

Respuesta

19

En primer lugar, si puede corregir func (puede modificar su fuente), luego soluciónelo. Si sus cálculos se pueden hacer con punteros, hágalo con punteros y punteros de retorno. A veces, existen razones válidas para trabajar con direcciones como enteros (por ejemplo, tratar problemas de alineación en un código especial). En ese caso, cambie func para usar el tipo uintptr_t (definido en stdint.h). Está diseñado para tratar punteros como enteros cuando sea necesario. (También hay intptr_t si la aritmética firmada es mejor por algún motivo, pero generalmente considero que el uintptr_t sin signo es menos problemático.) Preferiblemente, func debe convertir el uintptr_t en un puntero al devolverlo, por lo que el tipo de devolución de func sería un puntero (a algo, tal vez some_struct o void).

Si no puede reparar func, puede usar moldes para decirle al compilador que tiene la intención de realizar las conversiones que se están realizando. Sin embargo, este mensaje de error particular le indica que no está simplemente convirtiendo un entero en un puntero, sino que está convirtiendo un entero de un tamaño (por ejemplo, cuatro bytes) en un puntero de otro tamaño (por ejemplo, ocho bytes). Es probable que este código se haya escrito originalmente para un sistema donde el tipo entero devuelto por func tenía el mismo tamaño que el tipo de puntero, pero ahora se está compilando en un sistema donde el tipo de puntero es mayor o menor que ese entero.

En ese caso, debe asegurarse de que el cálculo realizado por func funciona en la nueva arquitectura. Si solo devuelve un valor de 32 bits, ¿siempre tendrá el valor correcto? Es decir, ¿nada se perderá por la falta de 32 bits altos? ¿Ninguna dirección que el func debe calcular excede nunca el valor máximo del tipo entero que utiliza? Si func usa tipos de entero con signo, considere también el bit de signo.

Si se ha asegurado de que el valor devuelto por func es correcto, puede usar moldes explícitos, como por ejemplo: some_struct *ptr = (some_struct *) (intptr_t) func();.

6

Mi gcc no da la advertencia que ha citado. También sería extraño porque no hay un molde en tu código.

tengo la advertencia

assignment makes pointer from integer without a cast 

Nota del "sin una conversión" parte. De este modo se puede hacer gcc silencio por colada (sin cambiar el comportamiento):

some_struct *ptr = (void*)func(); 

Entonces, usted recibirá su advertencia ("fundido al puntero desde un entero de tamaño diferente") si y sólo si el tipo de retorno de func no se ajusta para direcciones Esto se puede silenciar proyectando adicionalmente func() en un tipo de entero adecuado, p. intptr_t:

some_struct *ptr = (void*)(intptr_t)func(); 

Todo esto bajo el supuesto de que realmente desea convertir el entero-mal tamaño de un puntero. Probablemente, volver a trabajar el código sea una mejor idea.

3

Hay dos posibilidades:

  1. func está lanzando un puntero real a un entero; luego se usa como un puntero.
  2. func devuelve un número entero que se almacena en un puntero; ptr se convierte posteriormente en un número entero y se utiliza como un número entero.

En el primer caso, el valor de retorno de func se perder información, y potencialmente chocar o peor, si int es más pequeño que el tamaño de un puntero de datos, que será en la mayoría 64-bit memory models (incluyendo Windows y Linux). En ese caso, debe cambiar el tipo de devolución de func a intptr_t; ver Using intptr_t instead of void*? y Why/when to use `intptr_t` for type-casting in C?.

En el segundo caso, no es un problema, pero para tratar los problemas de endianidad debe enviar a través de intptr_t: some_struct *ptr = (some_struct *)(intptr_t)func(); y más tarde int value = (int)(intptr_t)ptr;. Ver GLib Type Conversion Macros para una discusión del problema.

Cuestiones relacionadas