Saltar al contenido

Doble puntero vs array de punteros (**array vs *array[])

Si encuentras alguna parte que te causa duda puedes dejarnos un comentario y te responderemos lo mas rápido que podamos.

Solución:

Si su profesor le dio el código al que hace referencia en su pregunta como un ejemplo del uso de matrices de punteros de punteros a punteros, no estoy seguro de cuánto bien hará realmente esa clase. Sospecho que se proporcionó como un ejercicio de depuración o puede haber sido su intento de solución. Independientemente, si simplemente compila con Advertencias habilitado, encontrará una serie de problemas que necesitan atención antes de avanzar a la depuración de su código.

Con respecto al código al que hace referencia, si bien puede usar un búfer de texto global, es mucho mejor que no use un búfer global y pase un puntero a sus datos según sea necesario. Hay algunas instancias, varias funciones de devolución de llamada, etc. que requieren datos globales, pero como regla general, esas son la excepción y no la regla.

Básicamente, tu pregunta se reduce a “¿Cómo utilizo correctamente un array de punteros y variables de punteros dobles (puntero a puntero a tipo). No hay forma de que el tema se pueda cubrir completamente en una respuesta porque hay demasiadas situaciones y contextos en los que uno u otro puede (o debería) usarse y por qué. Sin embargo, es de esperar que algunos ejemplos le ayuden a comprender las diferencias básicas.

Empezando por el array de punteros para escribir (p.ej char *array[]). Generalmente se ve en esa forma como un argumento de función. Cuando se declara como una variable, va seguida de una inicialización. p.ej:

char *array[] =  "The quick",
                  "brown fox",
                  "jumps over",
                  "the lazy dog." ;

char *array[]; por sí misma como una declaración de variable no es válida debido a la falta array tamaño entre [..]. Cuando se usa globalmente, como en su ejemplo, el compilador aceptará la declaración, pero advertir se supone que la declaración tiene un elemento.

Los elementos de array declarados anteriormente son punteros para escribir char. Específicamente, los elementos son indicadores de la string-literales creado por la declaración. Se puede acceder a cada una de las cadenas mediante el puntero asociado en array como array[0], ... array[3].

A puntero a puntero para escribir (doble puntero), es exactamente lo que implica su nombre. Es un puntero, eso sostiene un puntero como su valor. En términos básicos, es un puntero que apunta a otro puntero. Se puede utilizar para acceder a los miembros de la array anterior asignando la dirección de array igual que:

char **p = array;

Dónde p[1] o *(p + 1) puntos a "brown fox"etc.

Alternativamente, una cantidad de puntero a puntero a tipo se puede asignar dinámicamente y usar para crear un array de punteros para escribir, que luego se pueden asignar y reasignar para manejar el acceso o el almacenamiento de un número desconocido de elementos. Por ejemplo, un breve ejemplo para leer un número desconocido de líneas de stdin, es posible que vea:

#define MAXL 128
#define MAXC 512
...
char **lines = NULL;
char buf[MAXC] = 0;
lines = malloc (MAXL * sizeof *lines);
size_t index = 0;
...
while (fgets (buf, MAXC, stdin)) 
    lines[index++] = strdup (buf);
    if (index == MAXL)
        /* reallocate lines */

Arriba tienes lines, un puntero a puntero a carácter, inicialmente NULL, que se usa para asignar MAXL (128) punteros a char. A continuación, se leen las líneas de stdin dentro buf, después de cada lectura exitosa, se asigna memoria para contener el contenido de buf y la dirección de inicio resultante para cada bloque de memoria se asigna a cada puntero line[index] dónde index es 0-127, y al incremento de index a 128, index se reasigna para proporcionar punteros adicionales y la lectura continúa.

Lo que hace que el tema sea más extenso de lo que se puede tratar en cualquier respuesta es que array de punteros o puntero a puntero para escribir puede ser para cualquier type. (int, struct, o como miembro de una estructura a un tipo diferente, o function, etc …) Se pueden utilizar listas-enlazadas, en la devolución de listados de directorios (p. ej. opendir), o de otras formas adicionales. Se pueden inicializar estáticamente, asignar dinámicamente, pasar como parámetros de función, etc. Hay demasiados contextos diferentes para cubrirlos todos. Pero en todos los casos, seguirán las reglas generales que se ven aquí y en la otra respuesta aquí y en 1000 respuestas más aquí en StackOverflow.

Terminaré con un breve ejemplo que puede utilizar para ver los diferentes usos básicos de la array y doble puntero. He proporcionado comentarios adicionales en la fuente. Esto solo proporciona un puñado de usos básicos diferentes y de static declaración y asignación dinámica:

#include 
#include 
#include 

int main (void) 

    /* array is a static array of 4 pointers to char, initialized to the 
       4 string-literals that a part of the declaration */
    char *array[] =  "The quick",
                    "brown fox",
                    "jumps over",
                    "the lazy dog." ;
    /* p is a pointer-to-pointer-to-char assigned the address of array */
    char **p = array;
    /* lines is a pointer-to-pointer-to-char initialized to NULL, used
       below to allocate 8 pointers and storage to hold 2 copes of array */
    char **lines = NULL;
    size_t narray = sizeof array/sizeof *array;
    size_t i;

    printf ("nprinting each string-literal at the address stored byn"
            "each pointer in the array of ponters named 'array':nn");
    for (i = 0; i < narray; i++)
        printf (" %sn", array[i]);

    printf ("nprinting each string using a pointer to pointer to char 'p':nn");
    for (i = 0; i < narray; i++, p++)
        printf (" %sn", *p);

    p = array;
    printf ("nprinting each line using a pointer to pointer"
            " to char 'p' with array notation:nn");
    for (i = 0; i < narray; i++)
        printf (" %sn", p[i]);

    /* allocate 8 pointers to char */
    lines = malloc (2 * narray * sizeof *lines);

    /* allocate memory and copy 1st 4-strings to lines (long way) */
    for (i = 0; i < narray; i++) 
        size_t len = strlen (array[i]);
        lines[i] = malloc (len * sizeof **lines + 1);
        strncpy (lines[i], array[i], len);
        lines[i][len] = 0;
    

    /* allocate memory and copy 1st 4-strings to lines 
       (using strdup - short way) */
    // for (i = 0; i < narray; i++)
    //     lines[i] = strdup (array[i]);

    /* allocate memory and copy again as last 4-strings in lines */
    p = array;
    for (i = 0; i < narray; i++, p++)
        lines[i+4] = strdup (*p);

    p = lines; /* p now points to lines instead of array */
    printf ("nprinting each allocated line in 'lines' using pointer 'p':nn");
    for (i = 0; i < 2 * narray; i++)
        printf (" %sn", p[i]);

    /* free allocated memory */
    for (i = 0; i < 2 * narray; i++)
        free (lines[i]);
    free (lines);

    return 0;

Hazme saber si tienes alguna pregunta. Es un tema extenso con un conjunto relativamente pequeño de reglas que se pueden aplicar de muchas formas diferentes y en diferentes contextos.

Mi profesor escribió eso **array es lo mismo que *array[]

Es decir true en algunos contextos y no true en otros contextos.

Si se usa en una función como argumento,

void foo(int **array) 

es lo mismo que

void foo(int *array[]) 

Cuando se declaran como variables,

int **array;

no es lo mismo que

int *array[];

Puedes añadir valor a nuestro contenido informacional asistiendo con tu veteranía en las notas.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *