C: diferencias entre puntero char y matriz [duplicado]

Resuelto Midnight Blue asked hace 15 años • 14 respuestas

Considerar:

char amessage[] = "now is the time";
char *pmessage = "now is the time";

Leí en The C Programming Language , segunda edición, que las dos declaraciones anteriores no hacen lo mismo.

Siempre pensé que una matriz es una forma conveniente de manipular punteros para almacenar algunos datos, pero claramente este no es el caso... ¿Cuáles son las diferencias "no triviales" entre matrices y punteros en C?

Midnight Blue avatar Aug 26 '09 23:08 Midnight Blue
Aceptado

Aquí hay un mapa de memoria hipotético que muestra los resultados de las dos declaraciones:

                0x00  0x01  0x02  0x03  0x04  0x05  0x06  0x07
    0x00008000:  'n'   'o'   'w'   ' '   'i'   's'   ' '   't'
    0x00008008:  'h'   'e'   ' '   't'   'i'   'm'   'e'  '\0'
        ...
amessage:
    0x00500000:  'n'   'o'   'w'   ' '   'i'   's'   ' '   't'
    0x00500008:  'h'   'e'   ' '   't'   'i'   'm'   'e'  '\0'
pmessage:
    0x00500010:  0x00  0x00  0x80  0x00

La cadena literal "ahora es el momento" se almacena como una matriz de caracteres de 16 elementos en la dirección de memoria 0x00008000. Es posible que no se pueda escribir en esta memoria; lo mejor es asumir que no lo es. Nunca debes intentar modificar el contenido de una cadena literal.

La declaracion

char amessage[] = "now is the time";

asigna una matriz de 16 elementos de caracteres en la dirección de memoria 0x00500000 y copia el contenido de la cadena literal en ella. Esta memoria se puede escribir; Puedes cambiar el contenido de un mensaje al contenido de tu corazón:

strcpy(amessage, "the time is now");

La declaracion

char *pmessage = "now is the time";

asigna un único puntero a char en la dirección de memoria 0x00500010 y le copia la dirección de la cadena literal.

Dado que pmessage apunta al literal de cadena, no debe usarse como argumento para funciones que necesitan modificar el contenido de la cadena:

strcpy(amessage, pmessage); /* OKAY */
strcpy(pmessage, amessage); /* NOT OKAY */
strtok(amessage, " ");      /* OKAY */
strtok(pmessage, " ");      /* NOT OKAY */
scanf("%15s", amessage);    /* OKAY */
scanf("%15s", pmessage);    /* NOT OKAY */

etcétera. Si cambió pmessage para que apunte a un mensaje :

pmessage = amessage;

entonces se puede utilizar en todos los lugares donde se pueda utilizar un mensaje .

John Bode avatar Aug 27 '2009 14:08 John Bode

Es cierto, pero es una diferencia sutil. Esencialmente, lo primero:

char amessage[] = "now is the time";

Define una matriz cuyos miembros viven en el espacio de pila del alcance actual, mientras que:

char *pmessage = "now is the time";

Define un puntero que reside en el espacio de pila del alcance actual, pero que hace referencia a la memoria en otro lugar (en este, "ahora es el momento" se almacena en otro lugar de la memoria, comúnmente una tabla de cadenas).

Además, tenga en cuenta que debido a que los datos que pertenecen a la segunda definición (el puntero explícito) no se almacenan en el espacio de pila del alcance actual, no se especifica exactamente dónde se almacenarán y no se deben modificar.

Como señalaron Mark, GMan y Pavel, también hay una diferencia cuando se utiliza el operador de dirección en cualquiera de estas variables. Por ejemplo, &pmessage devuelve un puntero de tipo char**, o un puntero a un puntero a caracteres, mientras que &amessage devuelve un puntero de tipo char(*)[16], o un puntero a una matriz de 16 caracteres (que, como un char**, debe eliminarse la referencia dos veces como señala litb).

Walt W avatar Aug 26 '2009 16:08 Walt W