2009-02-23 16 views
44

Estoy un poco sorprendido por lo siguiente.Asignar cadenas a matrices de caracteres

Ejemplo 1:

char s[100] = "abcd"; // declare and initialize - WORKS 

Ejemplo 2:

char s[100]; // declare 
s = "hello"; // initalize - DOESN'T WORK ('lvalue required' error) 

me pregunto por qué el segundo enfoque no funciona. Parece natural que debería (funciona con otros tipos de datos)? ¿Podría alguien explicarme la lógica detrás de esto?

Respuesta

38

Al inicializar una matriz, C le permite llenar con valores. por lo

char s[100] = "abcd"; 

es básicamente el mismo que

int s[3] = { 1, 2, 3 }; 

pero no permite que hagan lo assignmend ya que s es una matriz y no un puntero libre. el significado de

s = "abcd" 

es asignar el valor del puntero de "ABCD" a 's' pero no se puede cambiar s desde entonces nada va a apuntar a la matriz.
Esto puede funcionar y funciona si s es char* - un puntero que puede apuntar a cualquier cosa.

si desea copiar la cadena sencilla utilización strcpy

+3

Buena respuesta, excepto que nunca debería usar plain strcpy por más tiempo. Use strncpy o strlcpy. – dwc

+3

Además, s debe ser const char *, no char *. – aib

+1

's [0] = 'x'; s [1] = 'y'; s [2] = 'z'; s [3] = 'm'; 'funciona si uno quiere reemplazar los caracteres de cadena uno por uno, incluso después de la inicialización. – RBT

9

Inicialización y asignación son dos operaciones distintas que usan el mismo operador ("=") aquí.

41

No existe una "cadena" en C. Las cadenas son matrices de caracteres, terminadas por NULL por convención. Como no puede asignar matrices en C, tampoco puede asignar cadenas. El azúcar sintáctico literal "hola" es para const char x[] = {'h','e','l','l','o','\0'};

La forma correcta sería:

char s[100]; 
strncpy(s, "hello", 100); 

o mejor aún:

#define STRMAX 100 
char s[STRMAX]; 
size_t len; 
len = strncpy(s, "hello", STRMAX); 
+0

No es el enfoque recomendado. Tenga cuidado con las rarezas de strncpy: http://stackoverflow.com/a/1258577/2974922 – nucleon

3
1 char s[100]; 
2 s = "hello"; 

En el ejemplo que nos ha facilitado, s es en realidad inicializado en la línea 1, no la línea 2. A pesar de que no asignó un valor de forma explícita en este punto, el compilador sí. En la línea 2, está realizando una operación de asignación y no puede asignar una matriz de caracteres a otra matriz de caracteres como esta. Tendrá que usar strcpy() o algún tipo de bucle para asignar cada elemento de la matriz.

2

Para ampliar Sparr's answer

Inicialización y asignación son dos operaciones distintas que pasan a utilizar el mismo operador ("=") aquí.

Piense en ello como esto:

Imagínese que hay 2 funciones, llamadas InitializeObject, y AssignObject.Cuando el compilador ve thing = value, mira el contexto y llama a uno InitializeObject si está creando un nuevo thing. Si no lo está, en su lugar llama al AssignObject.

Normalmente esto está bien ya que InitializeObject y AssignObject suelen comportarse de la misma manera. Excepto cuando se trata de arreglos de caracteres (y algunos otros casos extremos), en cuyo caso se comportan de manera diferente. ¿Por qué hacer esto? Bueno, esa es una publicación completamente distinta que involucra a la pila frente al montón, y así sucesivamente.

PD: Como acotación al margen, pensando que de esta manera también ayudará a entender constructores de copia y otras cosas si alguna vez se aventura en C++

0

Tenga en cuenta que todavía se puede hacer:

s[0] = 'h'; 
s[1] = 'e'; 
s[2] = 'l'; 
s[3] = 'l'; 
s[4] = 'o'; 
s[5] = '\0'; 
+0

Es mucho más fácil y mejor usar strncpy(), aunque estoy bastante seguro de que strncpy() hace exactamente esto internamente. –

+0

Por supuesto. Pero esto es lo más cercano a 's = "hola";' De hecho, esto debería haberse implementado en C, ya que puedes asignar estructuras. – aib

+0

Es decir, la copia de miembros por asignación en estructuras pero no en matrices no tiene sentido. – aib

-3

Lo que me gustaría utilizar es

char *s = "abcd"; 
+0

La mayoría de nosotros no lo haría, porque corre el riesgo de un comportamiento indefinido. Lo anterior solo es seguro para 'const char *'. –

0

puede utilizar este:

yylval.sval=strdup("VHDL + Volcal trance..."); 

Donde yylval es char *. strdup de hace el trabajo.

+0

strdup de hace el trabajo :) – Yekatandilburg

Cuestiones relacionadas