267 votos

¿Cuál es la diferencia entre char s[] y char *s?

En C, se puede utilizar un literal de cadena en una declaración como ésta:

char s[] = "hello";

o así:

char *s = "hello";

¿Cuál es la diferencia? Quiero saber qué ocurre realmente en términos de duración del almacenamiento, tanto en tiempo de compilación como de ejecución.

300voto

Rickard Puntos 2411

La diferencia aquí es que

char *s = "Hello world";

colocará "Hello world" en el partes de la memoria de sólo lectura y haciendo s un puntero a que hace que cualquier operación de escritura en esta memoria sea ilegal.

Mientras se hace:

char s[] = "Hello world";

pone la cadena literal en la memoria de sólo lectura y copia la cadena a la memoria recién asignada en la pila. De este modo, se hace

s[0] = 'J';

legal.

78voto

bdonlan Puntos 90068

En primer lugar, en los argumentos de la función, son exactamente equivalentes:

void foo(char *x);
void foo(char x[]); // exactly the same in all respects

En otros contextos, char * asigna un puntero, mientras que char [] asigna un Array. ¿Dónde va la cadena en el primer caso, te preguntarás? El compilador asigna secretamente un Array anónimo estático para contener el literal de la cadena. Así que:

char *x = "Foo";
// is approximately equivalent to:
static const char __secret_anonymous_array[] = "Foo";
char *x = (char *) __secret_anonymous_array;

Tenga en cuenta que nunca debe intentar modificar el contenido de este Array anónimo a través de este puntero; los efectos son indefinidos (a menudo significan una caída):

x[1] = 'O'; // BAD. DON'T DO THIS.

El uso de la sintaxis Array lo asigna directamente a la nueva memoria. Por lo tanto, la modificación es segura:

char x[] = "Foo";
x[1] = 'O'; // No problem.

Sin embargo, el Array sólo vive mientras su ámbito de contención, así que si usted hace esto en una función, no devuelva o filtre un puntero a este Array - haga una copia en su lugar con strdup() o similar. Si el Array se asigna en el ámbito global, por supuesto, no hay problema.

43voto

caf Puntos 114951

Esta declaración:

char s[] = "hello";

Crea un objeto - un char Matriz de tamaño 6, llamada s inicializado con los valores 'h', 'e', 'l', 'l', 'o', '\0' . El lugar en el que se asigna este Array en la memoria, y el tiempo que vive, depende del lugar en el que aparece la declaración. Si la declaración está dentro de una función, vivirá hasta el final del bloque en el que está declarada, y casi seguro que se asignará en la pila; si está fuera de una función, estará probablemente se almacenan dentro de un "segmento de datos inicializado" que se carga desde el archivo ejecutable en la memoria escribible cuando se ejecuta el programa.

Por otro lado, esta declaración:

char *s ="hello";

Crea dos objetos:

  • a Sólo lectura Conjunto de 6 char s que contienen los valores 'h', 'e', 'l', 'l', 'o', '\0' que no tiene nombre y tiene duración del almacenamiento estático (lo que significa que vive durante toda la vida del programa); y
  • una variable de tipo puntero-a-car, llamada s que se inicializa con la ubicación del primer carácter en ese Array sin nombre y de sólo lectura.

El Array de sólo lectura sin nombre se encuentra normalmente en el segmento "texto" del programa, lo que significa que se carga desde el disco en la memoria de sólo lectura, junto con el propio código. La ubicación del s de la variable puntero en la memoria depende de dónde aparezca la declaración (igual que en el primer ejemplo).

36voto

John Bode Puntos 33046

Dadas las declaraciones

char *s0 = "hello world";
char s1[] = "hello world";

suponga el siguiente mapa de memoria hipotético:

                    0x01  0x02  0x03  0x04
        0x00008000: 'h'   'e'   'l'   'l'
        0x00008004: 'o'   ' '   'w'   'o'
        0x00008008: 'r'   'l'   'd'   0x00
        ...
s0:     0x00010000: 0x00  0x00  0x80  0x00
s1:     0x00010004: 'h'   'e'   'l'   'l'
        0x00010008: 'o'   ' '   'w'   'o'
        0x0001000C: 'r'   'l'   'd'   0x00

La cadena literal "hello world" es una matriz de 12 elementos de char ( const char en C++) con una duración de almacenamiento estática, lo que significa que la memoria para ella se asigna cuando el programa se inicia y permanece asignada hasta que el programa termina. Intentar modificar el contenido de un literal de cadena invoca un comportamiento indefinido.

La línea

char *s0 = "hello world";

define s0 como un puntero a char con una duración de almacenamiento automática (lo que significa que la variable s0 sólo existe para el ámbito en el que se declara) y copia el dirección de la cadena literal ( 0x00008000 en este ejemplo). Tenga en cuenta que, dado que s0 apunta a un literal de cadena, no debe utilizarse como argumento de ninguna función que intente modificarlo (p. ej, strtok() , strcat() , strcpy() etc.).

La línea

char s1[] = "hello world";

define s1 como una matriz de 12 elementos de char (la longitud se toma del literal de la cadena) con una duración de almacenamiento automática y copia el contenidos del literal al Array. Como puedes ver en el mapa de memoria, tenemos dos copias de la cadena "hello world" la diferencia es que se puede modificar la cadena contenida en s1 .

s0 y s1 son intercambiables en la mayoría de los contextos; he aquí las excepciones:

sizeof s0 == sizeof (char*)
sizeof s1 == 12

type of &s0 == char **
type of &s1 == char (*)[12] // pointer to a 12-element array of char

Puede reasignar la variable s0 para apuntar a una cadena literal diferente o a otra variable. No se puede reasignar la variable s1 para apuntar a un Array diferente.

10voto

Charles Bailey Puntos 244082
char s[] = "hello";

declara s para ser un Array de char que es lo suficientemente largo para mantener el inicializador (5 + 1 char s) e inicializa el Array copiando los miembros de la cadena literal dada en el Array.

char *s = "hello";

declara s para ser un puntero a uno o más (en este caso más) char y lo dirige directamente a una ubicación fija (de sólo lectura) que contiene el literal "hello" .

Iteramos.com

Iteramos es una comunidad de desarrolladores que busca expandir el conocimiento de la programación mas allá del inglés.
Tenemos una gran cantidad de contenido, y también puedes hacer tus propias preguntas o resolver las de los demás.

Powered by:

X