aoeu
¿Estas dos líneas de código logran el mismo resultado? Si tuviera estas líneas en una función, ¿la cadena está almacenada en la pila en ambos casos? ¿Hay alguna razón sólida por la que deba usar uno sobre el otro, además de no tener que declarar el terminador nulo en la primera línea de código?
char s[] = "string";
char* s = "string\0";
No, esas dos líneas no consiguen el mismo resultado.
char s[] = "string"
da como resultado una matriz modificable de 7 bytes, que inicialmente se llena con el contenido 's' 't' 'r' 'i' 'n' 'g' '\0'
(todo copiado en tiempo de ejecución desde el literal de cadena).
char *s = "string"
da como resultado un puntero a algunos solo lectura memoria que contiene la “cadena” literal de cadena.
Si desea modificar el contenido de su cadena, entonces el primero es el único camino a seguir. Si solo necesita acceso de solo lectura a una cadena, entonces el segundo será un poco más rápido porque no es necesario copiar la cadena.
En ambos casos, no es necesario especificar un terminador nulo en el literal de cadena. El compilador se encargará de eso por usted cuando encuentre el cierre “.
-
Además, el segundo solo está permitido por horribles motivos heredados. Deberías usar
const char *s = "string";
–Steve Jessop
29 de octubre de 2010 a las 11:56
-
@Steve: para C ++, estaría completamente de acuerdo contigo. Para C, tiendo a dar un poco más de margen, porque en la práctica hay demasiadas formas en que el
const
se interpone en tu camino. (Eso también se conoce como envenenamiento constante)–Bart van Ingen Schenau
29 de octubre de 2010 a las 13:49
-
Si estoy usando bibliotecas dudosas, estoy de acuerdo contigo (a veces). Si el código está bajo mi control, lo arreglo para que
const
no se interpone en mi camino. La alternativa es tomar copias de las cadenas que deben pasarse como parámetros no constantes a las API dudosas. A veces, eso es factible, por ejemplo, si la cadena que se pasa es un literal definido cerca de la llamada, o como global, simplemente use la primera de las dos opciones anteriores. Otras veces es un PITA, en cuyo caso podría recibir el golpe de strdup o desecharlo.const
(que es “inseguro”, pero ya está utilizando una API “insegura”).–Steve Jessop
29 de octubre de 2010 a las 15:03
-
La segunda versión es muy útil para arreglos de cadenas constantes de diferentes longitudes o inclusión de cadenas constantes dentro de estructuras (aunque tiendo a usar
const
en la declaración si puedo).– ganso nate
29 de octubre de 2010 a las 15:29
-
¿Por qué no podemos modificar el segundo? Tengo una comprensión básica de la pila, así que por favor sea amable.
– Karan Singh
27 de enero de 2017 a las 14:39
La diferencia entre estos dos:
char a[] = "string";
char* b = "string";
es que a es en realidad una matriz estática en la pila, mientras que b es un puntero a una constante. Puede modificar el contenido de a, pero no b.
Andrei
Además de las otras respuestas, intentaré explicar por qué no puede modificar el *s
variable más adelante en el flujo del programa.
Conceptualmente cuando un programa se carga en memoria tiene 3 áreas (segmentos):
- segmento de código: el texto de su programa se almacena aquí (es un área de solo lectura)
- segmento de datos: contiene variables globales o estáticas que tienen un valor predefinido y se pueden modificar
- segmento de pila: aquí se cargan las funciones a medida que se llaman. El conjunto de valores (un marco de pila) insertado en la pila para cada llamada de función que contiene la dirección de retorno de la función y las variables locales.
en tu caso el s[]
variable es una variable local (matriz), en el main()
función, que se inicializa con el valor "string"
. Por lo tanto, se almacena en la pila y se puede modificar.
El *s
variable es un puntero que apunta a la dirección de "string\0"
, una constante ubicada en el segmento de código. Al ser un área de solo lectura, no puede modificar su contenido.
Solo como información, no necesita el \0 en el segundo ejemplo. Cuando se usan comillas dobles, \0 siempre se inserta en la matriz.
– RMAAlmeida
29 de octubre de 2010 a las 13:09
Y solo por el vocabulario, de lo que está hablando no son asignaciones, sino declaraciones con inicializadores. Obedecen reglas diferentes. Por ejemplo, su primera declaración no se permitiría como una asignación, no puede asignar matrices.
– Jens Gusted
29 de octubre de 2010 a las 16:38
posible duplicado de C: diferencias entre puntero y matriz
– Jens Gusted
29 de octubre de 2010 a las 16:42