Entonces, vi esto:
error:(NSError **)error
en el documento de Apple. ¿Por qué dos estrellas? ¿Cuál es el significado?
allyn
Entonces, vi esto:
error:(NSError **)error
en el documento de Apple. ¿Por qué dos estrellas? ¿Cuál es el significado?
mipadi
Una “doble estrella” es un puntero a un puntero. Entonces NSError **
es un puntero a un puntero a un objeto de tipo NSError
. Básicamente le permite devolver un objeto de error de la función. Puede crear un puntero a un NSError
objeto en su función (llámelo *myError
), y luego hacer algo como esto:
*error = myError;
para “devolver” ese error a la persona que llama.
En respuesta a un comentario publicado a continuación:
No puede simplemente usar un NSError *
porque en C, los parámetros de la función se pasan por valor—es decir, los valores son copiado cuando se pasa a una función. Para ilustrar, considere este fragmento de código C:
void f(int x)
{
x = 4;
}
void g(void)
{
int y = 10;
f(y);
printf("%d\n", y); // Will output "10"
}
La reasignación de x
en f()
no afecta el valor del argumento fuera de f()
(en g()
por ejemplo).
Del mismo modo, cuando se pasa un puntero a una función, su valor se copia y la reasignación no afectará el valor fuera de la función.
void f(int *x)
{
x = 10;
}
void g(void)
{
int y = 10;
int *z = &y;
printf("%p\n", z); // Will print the value of z, which is the address of y
f(z);
printf("%p\n", z); // The value of z has not changed!
}
Por supuesto, sabemos que podemos cambiar el valor de lo que z
apunta a con bastante facilidad:
void f(int *x)
{
*x = 20;
}
void g(void)
{
int y = 10;
int *z = &y;
printf("%d\n", y); // Will print "10"
f(z);
printf("%d\n", y); // Will print "20"
}
Entonces, es lógico que, para cambiar el valor de lo que un NSError *
apunta a, también tenemos que pasar un puntero al puntero.
hola, llego un poco tarde aquí. Me gustaría preguntar: ¿por qué debemos pasar un puntero a un puntero a NSError o en general para devolver un objeto? Por ejemplo de lo anterior, si solo pasamos un puntero a un objeto, ¿bastaría con esto: error = myError? (Habla: el error es un puntero a mi nuevo objeto de error myError)? Espero que pueda explicar mejor la justificación del uso de un puntero doble. Muchas gracias de antemano.
– Unheilig
8 de enero de 2014 a las 2:52
@Unheilig: actualicé mi respuesta con una respuesta a su pregunta.
– mipadi
8 de enero de 2014 a las 9:14
Gracias por escribir, pero te referías a int f(int **x)
en tu último ejemplo, ¿verdad? Y si es así, ¿debería esto… printf("%d\n", y);
– también se cambiará a: printf("%d\n", &y);
(agregado &
para y
) en el void
método en lugar de y
¿así como?
– Unheilig
8 de enero de 2014 a las 14:57
Además, creo que hay un problema en el código del segundo ejemplo con tipos incompatibles, es decir, en el método void f(int*)
Cuando tu lo hagas x = 10
(necesita desreferenciarse *
). Gracias.
– Unheilig
08/01/2014 a las 15:57
@Unheilig: el ejemplo es correcto, aunque quizás un poco confuso, pero estaba demostrando que necesita un puntero a su tipo de datos base para cambiar el valor. En el caso de un int
esto es un int *
; siguiendo la misma lógica, en el caso de NSError *
siendo su tipo de datos base, es NSError **
.
– mipadi
9 de enero de 2014 a las 4:04
En C todo pasa por valor. Si desea cambiar el valor de algo, le pasa la dirección (que pasa el valor de la dirección de memoria). Si desea cambiar hacia dónde apunta un puntero, pase la dirección del puntero.
“todo pasa por el valor” –esta prolija oración lo dice todo. ¡Gracias!
–Jim Chang
7 oct 2012 a las 13:51
En C, una estrella doble es un puntero a un puntero. Hay un par de razones para hacer esto. La primera es que el puntero podría ser una matriz de punteros. Otra razón sería pasar un puntero a una función, donde la función modifica el puntero (similar a un parámetro de “salida” en otros idiomas).
Kumarsunil
La estrella doble (**
) la notación no es específica para inicializar una variable en una clase. Es simplemente una doble referencia indirecta a un objeto.
float myFloat; // an object
float *myFloatPtr; // a pointer to an object
float **myFloatPtrPtr; // a pointer to a pointer to an object
myFloat = 123.456; // initialize an object
myFloatPtr = &myFloat; // initialize a pointer to an object
myFloatPtrPtr = myFloatPtr; // initialize a pointer to a pointer to an object
myFloat; // refer to an object
*myFloatPtr; // refer to an object through a pointer
**myFloatPtrPtr; // refer to an object through a pointer to a pointer
*myFloatPtrPtr; // refer to the value of the pointer to the object
La notación de puntero doble se utiliza cuando la persona que llama tiene la intención de que uno de sus propios punteros deba ser modificado por una llamada de función, por lo que la dirección del puntero, en lugar de la dirección del objeto, se pasa a la función.
Un ejemplo podría ser el uso de una lista enlazada. La persona que llama mantiene un puntero al primer nodo. La persona que llama invoca funciones para buscar, agregar y eliminar. Si esas operaciones implican agregar o eliminar el primer nodo, entonces el puntero de la persona que llama tiene que cambiar, no el puntero .next en ninguno de los nodos, y necesita la dirección del puntero para hacer eso.
Si es algo como C entonces **
significa un puntero a un puntero.
Objective-C es un superconjunto estricto de C. Nada de C es diferente.
– Peter Hosey
2 de marzo de 2009 a las 22:43
Objective-C es un superconjunto estricto de C. Nada de C es diferente.
– Peter Hosey
2 de marzo de 2009 a las 22:43