2009-01-04 20 views
11

Estoy leyendo un código en la implementación Ogre3D y no puedo entender qué significa una variable de tipo void *. ¿Qué significa un puntero a void en C++?Puntero a vacío en C++?

Respuesta

39

Un puntero a void, void* puede apuntar a cualquier objeto:

int a = 5; 
void *p = &a; 

double b = 3.14; 
p = &b; 

No se puede eliminar la referencia, incremento o decremento ese puntero, porque no se sabe qué tipo apuntar a. La idea es que void* se pueda usar para funciones como memcpy que simplemente copian bloques de memoria y no les importa el tipo que copian.

+0

waw - ¡No me di cuenta de que no se podía incrementar el vacío *! ¡Gracias! – xtofl

+0

Bastantes compiladores le permitirán: suponen que todos los tipos de punteros son de 32 bits. Esto es incorrecto, pero común en Windows donde la gente asume 32bit x86. –

+0

@mgb: Nunca he visto un compilador así. – dalle

4

Es sólo un puntero genérico, que se utiliza para pasar datos cuando no se conoce el tipo. Tienes que lanzarlo al tipo correcto para usarlo.

2

Puntero a cualquier cosa - solo un trozo de memoria con la que puedes jugar - podría ser un objeto, podría ser un char. Tienes que hacer el reparto para hacer algo útil con él.

2

Building off my prior posting...


ATENCIÓN: Todas las direcciones de memoria aquí son ficticios. Solo los estoy inventando para ilustrar un punto.


Dado:

int data[] = {10,11,12}; 

Ahora tenemos:

0xffff0000-0xffff0003 with a value of (int)(10) 
0xffff0004-0xffff0007 with a value of (int)(11) 
0xffff0008-0xffff000b with a value of (int)(12) 

(estoy no va a entrar en bigEndian vs orden de bytes ascendente hacia la izquierda aquí.)

Si tenemos:

int * p = data; 

Ahora tenemos otra posición de memoria en otro lugar, dicen:

0xaaaa0000-0xaaaa0003 with a value of (int*)0xffff0000 

podemos utilizar p [1] [o * (p + 1)] para referirse a * (int *) (0xffff0004) [= 11] como sizeof (int) = 4 y 0xffff0000 + sizeof (int) = 0xffff0004.

Si tenemos:

void * v = data; 

Ahora tenemos otra posición de memoria en otro lugar, por ejemplo:

0xbbbb0000-0xbbbb0003 with a value of (void*)0xffff0000. 

Sin embargo, el vacío No tiene ninguna información asociada sizeof().No podemos incrementar o disminuir el puntero. No podemos desreferenciar para acceder a los datos almacenados en 0xffff0000. Solo podemos utilizar el valor como una dirección de memoria sin formato.

Si queremos utilizar los datos almacenados en (void *) 0xffff0000, primero debemos convertirlo al tipo apropiado.

Dicho esto, (void *) sigue siendo bastante útil como medio para pasar direcciones a estructuras de datos arbitrarias. Por ejemplo, memset(). No importa si estoy poniendo a cero struct tm o struct sockaddr. Solo necesitamos un puntero a la estructura y su tamaño.

(Esto debería ser evidente, pero ... Cuidado con el uso de memset a cero fuera de una instancia de clase y, al hacerlo, sobrescribir la tabla de puntero virtual.)

1

Un puntero nulo no puede apuntar a un miembro de la clase en C++.

+0

Así es, son punteros de diferentes tamaños. – Joshua

+0

creo que se debe a que los indicadores de miembros son completamente diferentes estructurados. Si lo desea, puede decir que viven en otro espacio de direcciones (y entonces la razón es la misma que la razón por la que no puede apuntar a una función usando 'void *'). Para los tamaños, un puntero de miembro de datos en GCC (después del Itanium ABI) tendrá el tamaño de un 'ptrdiff_t' - es igual al tamaño de un' int * 'en mi PC - el espacio de direcciones es el desplazamiento desde el inicio del objetar a su último miembro compensado. Para punteros a funciones miembro, el tamaño suele ser mayor, además, por supuesto. –