En C, uno puede usar un literal de cadena en una declaración como esta:
char s[] = "hello";
o así:
char *s = "hello";
Entonces cuál es la diferencia? Quiero saber qué sucede realmente en términos de duración del almacenamiento, tanto en tiempo de compilación como de ejecución.
![¿Cuál es la diferencia entre char s[] y char*s? 1 avatar de usuario](https://www.revivemyvote.com/wp-content/uploads/¿Cual-es-la-diferencia-entre-char-s-y-chars.png)
bdonlan
En primer lugar, en los argumentos de 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 una matriz. ¿Adónde va la cuerda en el primer caso, te preguntarás? El compilador asigna en secreto una matriz anónima estática para contener el literal de cadena. Asi 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 esta matriz anónima a través de este puntero; los efectos no están definidos (a menudo significan un bloqueo):
x[1] = 'O'; // BAD. DON'T DO THIS.
El uso de la sintaxis de matriz 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, la matriz solo vive mientras su alcance contiene, por lo que si hace esto en una función, no devuelva ni filtre un puntero a esta matriz; haga una copia en su lugar con strdup()
o similar. Si la matriz se asigna en el ámbito global, por supuesto, no hay problema.
![¿Cuál es la diferencia entre char s[] y char*s? 2 avatar de usuario](https://www.revivemyvote.com/wp-content/uploads/1649924230_525_¿Cual-es-la-diferencia-entre-char-s-y-chars.png)
cristo
Un ejemplo de la diferencia:
printf("hello" + 2); //llo
char a[] = "hello" + 2; //error
En el primer caso, la aritmética de punteros está funcionando (las matrices pasadas a una función se descomponen en punteros).
![¿Cuál es la diferencia entre char s[] y char*s? 3 avatar de usuario](https://www.revivemyvote.com/wp-content/uploads/¿Cual-es-la-diferencia-entre-char-s-y-chars.jpg)
ilkkachu
Dadas las declaraciones
char *s0 = "hello world";
char s1[] = "hello world";
asuma el siguiente mapa de memoria hipotético (las columnas representan caracteres en desplazamientos de 0 a 3 de la dirección de fila dada, por ejemplo, el 0x00
en la esquina inferior derecha está en la dirección 0x0001000C + 3
= 0x0001000F
):
+0 +1 +2 +3
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
El literal de cadena "hello world"
es una matriz de 12 elementos de char
(const char
en C++) con duración de almacenamiento estática, lo que significa que la memoria se asigna cuando se inicia el programa y permanece asignada hasta que finaliza el programa. 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 duración de almacenamiento automático (es decir, la variable s0
sólo existe para el ámbito en el que se declara) y copia el dirección del literal de cadena (0x00008000
en este ejemplo) a ella. Tenga en cuenta que desde s0
apunta a un literal de cadena, no debe usarse como argumento para ninguna función que intente modificarlo (por ejemplo, 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 cadena) con duración de almacenamiento automático y copia el contenido del literal a la matriz. Como puede ver en el mapa de memoria, tenemos dos copias de la cadena "hello world"
; la diferencia es que puede modificar la cadena contenida en s1
.
s0
y s1
son intercambiables en la mayoría de los contextos; Aquí están 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 un literal de cadena diferente o a otra variable. No puede reasignar la variable s1
para apuntar a una matriz diferente.
Esta declaración:
char s[] = "hello";
crea uno objeto – un char
arreglo de tamaño 6, llamado s
inicializado con los valores 'h', 'e', 'l', 'l', 'o', '\0'
. La ubicación de esta matriz en la memoria y el tiempo de vida depende de dónde aparezca la declaración. Si la declaración está dentro de una función, vivirá hasta el final del bloque en el que se declara, y casi con certeza se ubicará en la pila; si está fuera de una función, lo hará probablemente almacenarse dentro de un “segmento de datos inicializados” que se carga desde el archivo ejecutable en la memoria grabable cuando se ejecuta el programa.
Por otro lado, esta declaración:
char *s ="hello";
crea dos objetos:
- un solo lectura matriz de 6
char
s que contiene 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 pointer-to-char, llamada
s
que se inicializa con la ubicación del primer carácter en esa matriz de solo lectura sin nombre.
La matriz de solo lectura sin nombre generalmente se encuentra en el segmento de “texto” del programa, lo que significa que se carga desde el disco a la memoria de solo lectura, junto con el código en sí. La ubicación de la s
La variable de puntero en la memoria depende de dónde aparece la declaración (como en el primer ejemplo).
c-faq.com/aryptr/index.html c-faq.com/charstring/index.html
– Sinan Ünür
9 de noviembre de 2009 a las 23:22
char *s=”hola”, aquí s puede apuntar cualquier otra cadena en tiempo de ejecución, quiero decir que no es un puntero constante, puede asignar otro valor en tiempo de ejecución p = “Nishant”, mientras que s[] aquí s es un puntero constante…. no se puede reasignar otra cadena pero podemos asignar otro valor de carácter en s[index].
–Nishant Kumar
16 mayo 2012 a las 14:49
@NishantQuerías decir … puedes asignar otro valor en tiempo de ejecución s = “Nishant”, mientras que s[] … ¿Tuviste? De lo contrario, es un poco confuso en el contexto.
– Yifangt
4 de marzo a las 4:26