¿Qué es la estrella doble (por ejemplo, NSError **)?

5 minutos de lectura

avatar de usuario
allyn

Entonces, vi esto:

error:(NSError **)error

en el documento de Apple. ¿Por qué dos estrellas? ¿Cuál es el significado?

avatar de usuario
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 intesto 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.

Echa un vistazo aquí para una explicación simple..

  • “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).

avatar de usuario
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

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad