numérico25
Buscaría esto, pero honestamente no sabría por dónde empezar porque no sé cómo se llama. He visto variables pasadas a funciones como esta:
myFunction((void**)&variable);
Lo que me confunde muchísimo porque todos esos me parecen familiares; Nunca los había visto juntos así antes.
¿Qué significa? Soy un novato, así que cuanto menos jerga, mejor, ¡gracias!
void*
es un “puntero a cualquier cosa”. void **
es otro nivel de direccionamiento indirecto: “puntero a puntero a cualquier cosa”. Básicamente, pasa eso cuando quiere permitir que la función devuelva un puntero de cualquier tipo.
&variable
toma la dirección de la variable. variable
ya debería ser una especie de puntero para que eso funcione, pero probablemente no lo sea void *
– podría ser, digamos int *
por lo que tomar su dirección resultaría en una int **
. Si la función toma void **
entonces necesitas lanzar a ese tipo.
(Por supuesto, debe devolver un objeto del tipo correcto; de lo contrario, el código de llamada fallará en el camino cuando intente usarlo de manera incorrecta).
-
ok, entonces la función de llamada tiene que solicitar el tipo void como argumento para que pueda convertir mi objeto en void. Pero supongo que la pregunta de seguimiento es ¿qué tiene que ofrecer el vacío de tipo de datos que sea beneficioso para la función? Si void representa un tipo de datos desconocido, significa que las propiedades y los valores también son desconocidos.
– numérico25
31 de mayo de 2010 a las 4:11
-
Le permite sortear la verificación de tipos que normalmente se realizaría; podría (por ejemplo) tener una función que tome un puntero a una función y un argumento para llamarla, luego devuelva el resultado. Si tuviera que especificar el tipo (por ejemplo, char*, int*, etc.), tendría que tener una función para cada tipo de argumento; usando void* puede usar los datos sin importar cuáles son los tipos reales.
– El Yobo
31 de mayo de 2010 a las 4:24
kim reece
Desmontarlo pieza por pieza…
myFunction lleva un puntero a un puntero de tipo void (lo que significa que podría apuntar a cualquier cosa). Se podría declarar algo como esto:
myFunction(void **something);
Cualquier cosa que pases tiene que tener ese tipo. Entonces, toma la dirección de un puntero y lo convierte con (void **) para que sea un puntero vacío. (Básicamente, despojándolo de cualquier idea sobre a qué apunta, de lo que el compilador podría quejarse de lo contrario).
Esto significa que &variable es la dirección (& hace esto) de un puntero, por lo que variable es un puntero. ¿A qué? ¡Quién sabe!
Aquí hay un fragmento más completo, para dar una idea de cómo encaja esto:
#include <stdio.h>
int myInteger = 1;
int myOtherInt = 2;
int *myPointer = &myInteger;
myFunction(void **something){
*something = &myOtherInt;
}
main(){
printf("Address:%p Value:%d\n", myPointer, *myPointer);
myFunction((void**)&myPointer);
printf("Address:%p Value:%d\n", myPointer, *myPointer);
}
Si compila y ejecuta esto, debería dar este tipo de salida:
Address:0x601020 Value:1
Address:0x601024 Value:2
Puede ver que myFunction cambió el valor de myPointer, lo que solo pudo hacer porque se pasó la dirección del puntero.
-
Oooo, está bien. Así que corrígeme si me equivoco. Un puntero vacío solo está destinado a contener cualquier tipo de tipo de datos. una vez que un tipo de datos específico se convierte en el puntero vacío, el puntero vacío se convierte en ese tipo de datos. y Por supuesto, no puedo pasar un puntero vacío a una función a menos que la función lo solicite.
– numérico25
31 de mayo de 2010 a las 4:20
-
Un puntero es solo un valor, una dirección en la memoria. Su tipo es una indicación para el compilador de a qué tipo de cosa apunta. Un puntero vacío es como decirle al compilador que no le va a decir a qué tipo podría apuntar el puntero. Al pasar parámetros, siempre debe coincidir con el tipo que la función declara aceptar. Entonces, si la función quiere un vacío ** y tiene un int **, debe convertirlo para que sea lo que espera la función.
-Kim Reece
31 de mayo de 2010 a las 4:32
en silico
Es un lanzamiento a un puntero a un void
puntero.
Esto se ve muy a menudo con funciones como CoCreateInstance()
en sistemas Windows.
ISomeInterface* ifaceptr = 0;
HRESULT hr = ::CoCreateInstance(CLSID_SomeImplementation, NULL, CLSCTX_ALL,
IID_ISomeInterface, (void**)&ifaceptr);
if(SUCCEEDED(hr))
{
ifaceptr->DoSomething();
}
El molde convierte el puntero en un ISomeInterface
puntero a un puntero a un void
puntero para que CoCreateInstance()
puede establecer ifaceptr
a un valor válido.
Como es un puntero a un void
puntero, la función puede generar punteros de cualquier tipo, según el ID de la interfaz (como IID_ISomeInterface).
-
Eso tiene sentido. Pero nunca escuché sobre el manejo de una variable de un tipo de datos desconocido. ¿Cómo manejaría CoCreateInstance ifaceptr, si no sabe de qué tipo es? en segundo lugar, el tamaño del vacío es arbitrario con respecto al tamaño del tipo de datos original.
– numérico25
31 de mayo de 2010 a las 4:06
-
CoCreateInstance siempre crea un puntero a un objeto COM y lo devuelve a través del
void**
parámetro. Le dices qué tipo quieres, en forma deIID_ISomeInterface
parámetro, y usted es responsable de usar typecasts correctamente para convertir elvoid**
en algo que puedas usar.–Ken Bloom
31 de mayo de 2010 a las 4:19
-
CoCreateInstance()
“sabe” de qué tipo debe ser el puntero de salida de acuerdo con la ID de la interfaz (eso es lo queIID_ISomeInterface
es para en el ejemplo). También, todo los punteros tienen el mismo tamaño para una arquitectura determinada (por ejemplo, todos los punteros en un sistema de 32 bits tienen 4 bytes, mientras que todos los punteros en un sistema de 64 bits tienen 8 bytes). No hay tal cosa como unvoid
tipo, pero puedes tenervoid
punteros Básicamente significa un puntero a cualquier tipo.– En silicio
31 de mayo de 2010 a las 4:20
-
Veo lo que estás diciendo. Y he visto variables en las que puede pasar una FLAG de tipo de datos variable. Nunca supe por qué, pero creo que ahora sé por qué. También supongo que tampoco puedes iniciar una variable de tipo void. Por ejemplo, void* myVar. Primero debe especificar un tipo de datos, luego convertirlo en un tipo vacío al llamar a una función que lo solicite. Corrígeme si me equivoco en eso.
– numérico25
31 de mayo de 2010 a las 4:29
-
Oh no, puedes declarar una variable de un
void*
tipo, comovoid* myVar;
. Simplemente no puede tener una variable de unvoid
tipo, comovoid myVar;
. No puedes hacer mucho con unvoid*
puntero, por lo que a menudo lo lanzamos a otra cosa.– En silicio
31 de mayo de 2010 a las 4:40
Es un puntero a un puntero a una variable con un tipo no especificado. Todos los punteros son del mismo tamaño, por lo que void*
solo significa “un puntero a algo pero no tengo idea de qué es”. A void**
también podría ser una matriz 2D de tipo no especificado.
que arroja &variable
a un void**
(es decir, un puntero a un puntero a void
).
Por ejemplo, si usted tiene algo a lo largo de las líneas de
void myFunction(void** arg);
int* variable;
Esto pasa la dirección de variable
(eso es lo que dice el unario-&
hace, toma la dirección) a myFunction()
.
lach
La variable es un puntero a algo de tipo indefinido (vacío). El operador & devuelve la dirección de esa variable, por lo que ahora tiene un puntero a un puntero de algo. Por lo tanto, el puntero se pasa a la función por referencia. La función podría tener un efecto secundario que cambia la memoria a la que hace referencia ese puntero. En otras palabras, llamar a esta función podría cambiar algo a lo que hace referencia el puntero original.