Atribuindo strings a matrizes de caracteres

Estou um pouco surpreso com o seguinte.

Exemplo 1:

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

Exemplo 2:

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

Eu estou querendo saber porque a segunda abordagem não funciona. Parece natural que deva (funciona com outros tipos de dados)? Alguém poderia me explicar a lógica por trás disso?

Ao inicializar uma matriz, C permite preenchê-lo com valores. assim

 char s[100] = "abcd"; 

é basicamente o mesmo que

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

mas não permite que você faça a atribuição, pois s é uma matriz e não um ponteiro livre. o significado de

 s = "abcd" 

é atribuir o valor de ponteiro de “abcd” a ‘s’, mas você não pode alterar s desde então, nada apontará para a matriz.
Isso pode e funciona se s é um char* – um ponteiro que pode apontar para qualquer coisa.

se você quiser copiar a string simples use strcpy

Não existe uma “string” em C. Strings são arrays de char, terminados por NULL por convenção. Como você não pode atribuir matrizes em C, também não é possível atribuir cadeias de caracteres. O literal “olá” é açúcar sintático para const char x[] = {'h','e','l','l','o','\0'};

A maneira correta seria:

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

ou melhor ainda:

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

Inicialização e atribuição são duas operações distintas que usam o mesmo operador (“=”) aqui.

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

No exemplo que você forneceu, s na verdade foi inicializado na linha 1, e não na linha 2. Mesmo que você não tenha atribuído um valor explicitamente neste ponto, o compilador fez isso. Na linha 2, você está executando uma operação de atribuição e não pode atribuir uma matriz de caracteres a outra matriz de caracteres como essa. Você terá que usar strcpy () ou algum tipo de loop para atribuir cada elemento da matriz.

Para expandir a resposta de Sparr

Inicialização e atribuição são duas operações distintas que usam o mesmo operador (“=”) aqui.

Pense nisso assim:

Imagine que existem duas funções, chamadas InitializeObject e AssignObject . Quando o compilador vê o thing = value , olha o contexto e chama um InitializeObject se você está fazendo uma thing nova. Se você não for, ele chama AssignObject .

Normalmente isso é bom como InitializeObject e AssignObject geralmente se comportam da mesma maneira. Exceto ao lidar com matrizes de caracteres (e alguns outros casos de borda), caso em que eles se comportam de maneira diferente. Por que fazer isso? Bem, esse é um outro post que envolve a pilha contra o heap e assim por diante.

PS: Como um aparte, pensar desta maneira também ajudará você a entender os construtores de cópias e outras coisas semelhantes se você se aventurar em C ++

Note que você ainda pode fazer:

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

Você pode usar isto:

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

Onde yylval é char *. O strdup faz o trabalho.

O que eu usaria é

 char *s = "abcd";