2009-05-07 16 views
14

Entiendo que tener un asterisco * es un puntero, ¿qué significa tener dos **?¿Qué significa tener dos asteriscos ** en Objective-C?

que se tropiezan con esto de la documentación:

- (NSAppleEventDescriptor *)executeAndReturnError:(NSDictionary **)errorInfo 
+0

conjetura salvaje: un puntero a puntero? :) – Constantin

+0

Sí, también estaba adivinando eso, pero no pude encontrar ninguna confirmación de Google. :) – John

Respuesta

32

Es un puntero a un puntero, al igual que en C (que, a pesar de su sintaxis de corchetes extraño, Objective-C se basa en):

char c; 
char *pc = &c; 
char **ppc = &pc; 
char ***pppc = &ppc; 

y así sucesivamente, hasta el infinito (o hasta te quedas sin espacio variable).

A menudo se utiliza para pasar un puntero a una función que debe ser capaz de cambiar el puntero en sí (como la reasignación de memoria para un objeto de tamaño variable).

=====

Después de su solicitud de un ejemplo que muestra cómo usarlo, aquí hay un código que escribí para otro post, que lo ilustra. Es una función appendStr() que gestiona sus propias asignaciones (aún debe liberar la versión final). Inicialmente establece la cadena (char *) en NULL y la función en sí asignará espacio según sea necesario.

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 

void appendToStr (int *sz, char **str, char *app) { 
    char *newstr; 
    int reqsz; 

    /* If no string yet, create it with a bit of space. */ 

    if (*str == NULL) { 
     *sz = strlen (app) + 10; 
     if ((*str = malloc (*sz)) == NULL) { 
      *sz = 0; 
      return; 
     } 
     strcpy (*str, app); 
     return; 
    } 

 

/* If not enough room in string, expand it. We could use realloc 
     but I've kept it as malloc/cpy/free to ensure the address 
     changes (for the program output). */ 

    reqsz = strlen (*str) + strlen (app) + 1; 
    if (reqsz > *sz) { 
     *sz = reqsz + 10; 
     if ((newstr = malloc (*sz)) == NULL) { 
      free (*str); 
      *str = NULL; 
      *sz = 0; 
      return; 
     } 
     strcpy (newstr, *str); 
     free (*str); 
     *str = newstr; 
    } 

    /* Append the desired string to the (now) long-enough buffer. */ 

    strcat (*str, app); 
} 

 

static void dump(int sz, char *x) { 
    if (x == NULL) 
     printf ("%8p [%2d] %3d [%s]\n", x, sz, 0, ""); 
    else 
     printf ("%8p [%2d] %3d [%s]\n", x, sz, strlen (x), x); 
} 

static char *arr[] = {"Hello.", " My", " name", " is", " Pax", 
         " and"," I", " am", " old."}; 

int main (void) { 
    int i; 
    char *x = NULL; 
    int sz = 0; 

    printf (" Pointer Size Len Value\n"); 
    printf (" ------- ---- --- -----\n"); 
    dump (sz, x); 
    for (i = 0; i < sizeof (arr)/sizeof (arr[0]); i++) { 
     appendToStr (&sz, &x, arr[i]); 
     dump (sz, x); 
    } 
} 

El código da el siguiente resultado. Se puede ver cómo el puntero cambia cuando la memoria asignada actualmente se queda sin espacio para la cadena expandida (en los comentarios):

Pointer Size Len Value 
------- ---- --- ----- 
# NULL pointer here since we've not yet put anything in. 
    0x0 [ 0]  0 [] 

# The first time we put in something, we allocate space (+10 chars). 
0x6701b8 [16]  6 [Hello.] 
0x6701b8 [16]  9 [Hello. My] 
0x6701b8 [16] 14 [Hello. My name] 

# Adding " is" takes length to 17 so we need more space. 
0x6701d0 [28] 17 [Hello. My name is] 
0x6701d0 [28] 21 [Hello. My name is Pax] 
0x6701d0 [28] 25 [Hello. My name is Pax and] 
0x6701d0 [28] 27 [Hello. My name is Pax and I] 

# Ditto for adding " am". 
0x6701f0 [41] 30 [Hello. My name is Pax and I am] 
0x6701f0 [41] 35 [Hello. My name is Pax and I am old.] 

En ese caso, se pasa en **str ya que se necesita para ser capaz de cambiar la *str valor.

=====

O lo siguiente, que hace una burbuja de desenrollado especie (oh, la vergüenza!) En las cadenas que no están en una matriz. Lo hace intercambiando directamente las direcciones de las cadenas.

#include <stdio.h> 

static void sort (char **s1, char **s2, char **s3, char **s4, char **s5) { 
    char *t; 

    if (strcmp (*s1, *s2) > 0) { t = *s1; *s1 = *s2; *s2 = t; } 
    if (strcmp (*s2, *s3) > 0) { t = *s2; *s2 = *s3; *s3 = t; } 
    if (strcmp (*s3, *s4) > 0) { t = *s3; *s3 = *s4; *s4 = t; } 
    if (strcmp (*s4, *s5) > 0) { t = *s4; *s4 = *s5; *s5 = t; } 

    if (strcmp (*s1, *s2) > 0) { t = *s1; *s1 = *s2; *s2 = t; } 
    if (strcmp (*s2, *s3) > 0) { t = *s2; *s2 = *s3; *s3 = t; } 
    if (strcmp (*s3, *s4) > 0) { t = *s3; *s3 = *s4; *s4 = t; } 

    if (strcmp (*s1, *s2) > 0) { t = *s1; *s1 = *s2; *s2 = t; } 
    if (strcmp (*s2, *s3) > 0) { t = *s2; *s2 = *s3; *s3 = t; } 

    if (strcmp (*s1, *s2) > 0) { t = *s1; *s1 = *s2; *s2 = t; } 
} 

int main (int argCount, char *argVar[]) { 
    char *a = "77"; 
    char *b = "55"; 
    char *c = "99"; 
    char *d = "88"; 
    char *e = "66"; 

    printf ("Unsorted: [%s] [%s] [%s] [%s] [%s]\n", a, b, c, d, e); 
    sort (&a,&b,&c,&d,&e); 
    printf (" Sorted: [%s] [%s] [%s] [%s] [%s]\n", a, b, c, d, e); 
    return 0; 
} 

que produce:

Unsorted: [77] [55] [99] [88] [66] 
    Sorted: [55] [66] [77] [88] [99] 

No importa el tipo de aplicación, simplemente observe que las variables se pasan como char ** de modo que se pueden intercambiar fácilmente. Cualquier tipo real probablemente estaría actuando sobre una verdadera matriz de datos en lugar de variables individuales, pero ese no es el punto del ejemplo.

+0

C y sus punteros me confunden ... :( –

+0

¿Puede explicar cómo lo usaría en el código? Esto todavía me deja perplejo sobre cómo usarlo. – John

+1

Guau, necesito un poco de tiempo para digerir ... pero gracias ! – John

1

Un puntero a un puntero.

1

En C, los punteros y las matrices se pueden tratar igual, lo que significa p. char * es una cadena (matriz de caracteres). Si desea pasar una matriz de matrices (por ejemplo, muchas cadenas) a una función, puede usar char **.

+0

Con una diferencia: sizeof (char [])! = Sizeof (char *): mucha gente ha sido mordida por esto. – paxdiablo

1

(Referencia: Más iOS 6 desarrollo)

En los métodos de Objective-C, argumentos, incluyendo punteros a objetos, son pasado por valor, lo que significa que el método llamado obtiene su propia copia del puntero que pasó. Entonces, si el método llamado quiere cambiar el puntero, a diferencia de los datos a los que señala el puntero, necesita otro nivel de direccionamiento indirecto. Por lo tanto, el puntero al puntero.

0

puntero a puntero

Como la definición de puntero dice que es una variable especial que puede almacenar la dirección de otra variable. Entonces la otra variable puede ser un puntero. Esto significa que es perfectamente legal que un puntero apunte a otro puntero.

Supongamos que tenemos un puntero p1 que apunta a otro puntero p2 que apunta a un carácter c. En la memoria, las tres variables se pueden visualizar como:

enter image description here

Así podemos ver que en la memoria, puntero p1 contiene la dirección del puntero p2. El puntero p2 tiene la dirección del carácter c.

Así p2 es puntero a carácter c, mientras p1 es puntero a p2 o también podemos decir que p2 es un puntero a puntero a carácter c.

Ahora, en el código p2 se puede declarar como:

char * p2 = & c;

Pero p1 se declara como:

char ** p1 = &p2;

Y vemos que p1 es un doble puntero (es decir puntero a un puntero a un carácter) y de ahí los dos * s en declaración.

Ahora,

  • p1 es la dirección de p2 es decir, 5000
  • *p1 es el valor en poder de p2 es decir, 8000
  • **p1 es el valor en 8000 es decir,c Creo que si más o menos claro el concepto, vamos a tomar un pequeño ejemplo:

Fuente: http://www.thegeekstuff.com/2012/01/advanced-c-pointers/

Para algunos de sus casos de uso:

Esto normalmente se utiliza para pasar un puntero a una función que debe ser capaz de cambiar el puntero en sí, algunos de sus casos de uso son:

  • Su Como errores de manejo, permite que el método de recepción controle a qué hace referencia el puntero. Consulte this pregunta
  • Para crear una estructura opaca, es decir, para que otros no puedan asignar espacio. Consulte this pregunta
  • En caso de expansión de memoria mencionada en las otras respuestas a esta pregunta.

dude en para corregir/mejorar esta respuesta como estoy aprendiendo:]

Cuestiones relacionadas