Como o array char é armazenado em C ++?
int main()
{
char c1[5]="abcde";
char c2[5]={'a','b','c','d','e'};
char *s1 = c1;
char *s2 = c2;
printf("%s",s1);
printf("%s",s2);
return 0;
}
Neste trecho de código, a matriz char C2 não retorna nenhum erro, mas a matriz char C1 retorna uma string muito longa. Eu sei que C1 deve exigir um tamanho de 6 para armazenar 5 caracteres, uma vez que armazena o \0(caractere NULL) no último índice. Mas estou confuso por que C2 funciona bem então?
Além disso, quando C2, é impressa utilizando %s, a saída é abcde@onde @é um personagem sem sentido. %scom printfimprime todos os caracteres a partir do endereço fornecido até que \0seja encontrado. Não entendo por que está imprimindo aquele caractere extra no final ?
Respostas
Eu sei que C1 deve exigir um tamanho de 6 para armazenar 5 caracteres, uma vez que armazena o
\0(caractere NULL) no último índice. Mas estou confuso por que C2 funciona bem então?
O compilador não reclama da inicialização de c2porque a inicialização com {'a','b','c','d','e'}não inclui implicitamente um caractere nulo de terminação.
Em contraste, inicializar com "abcde"inclui um caractere nulo: O padrão C define um literal de string para incluir um caractere nulo de terminação, portanto, char c1[5]="abcde";inicializa nominalmente uma matriz de 5 elementos com 6 valores. O padrão C não requer um aviso ou erro neste caso porque C 2018 6.7.9 14 indica que o caractere nulo pode ser desprezado se o array não tiver espaço para ele. No entanto, o compilador que você está usando 1 optou por emitir uma mensagem de aviso porque essa forma de inicialização geralmente indica um erro: O programador tentou inicializar um array com uma string, mas não há espaço para a string completa.
Em C, matrizes de caracteres e strings são coisas diferentes: uma matriz é uma sequência de valores e uma matriz de caracteres pode conter qualquer valor arbitrário desses caracteres, incluindo nenhum valor zero no final e possíveis valores zero no meio. Por exemplo, se temos um buffer de bytes de um arquivo binário, os bytes são apenas valores inteiros para nós; seu significado como caracteres que podem ser impressos é irrelevante. Uma string é uma sequência de caracteres que termina com um caractere nulo. Ele não pode ter valores de zero internos porque o primeiro caractere nulo marca o fim.
Portanto, quando você define um array de caracteres como char c1[5], o compilador não sabe automaticamente se você pretende usá-lo para armazenar strings ou se pretende usá-lo como um array de valores arbitrários. Quando você inicializa o array com uma string, seu compilador está essencialmente descobrindo que você pretende usar o array para armazenar strings e avisa se a string usada para inicializar o array não cabe. Quando você inicializa o array com uma lista de valores, seu compilador basicamente imagina que você pode estar usando-o para manter valores arbitrários e não avisa que pode haver um terminador ausente.
Além disso, quando C2, é impressa utilizando
%s, a saída éabcde@onde@é um personagem sem sentido.
Como c2não tem um caractere de terminação, a tentativa de imprimi-lo sai do final do array, resultando em um comportamento não definido pelo padrão C. Normalmente, printfcontinua lendo a memória além do array, imprimindo o que quer que esteja lá até atingir um caractere nulo.
Nota de rodapé
1 Isso pressupõe que você está realmente usando um compilador C para compilar este código-fonte. C ++ tem regras diferentes e não permite que uma matriz sendo inicializada com uma string literal seja muito curta para incluir o caractere nulo de terminação.
Você criou duas strings não terminadas. Faça seus arrays grandes o suficiente para conter o terminador nulo e você evitará este comportamento indefinido:
char c1[6] = "abcde";
char c2[6] = {'a','b','c','d','e','\0'};
Estritamente, falar o último realmente não requer o '\0'. Esta declaração é equivalente e incluirá o terminador nulo:
char c2[6] = {'a','b','c','d','e'};
Eu pessoalmente prefiro a primeira forma, mas com a conveniência adicional de ser capaz de omitir o comprimento explícito:
char c1[] = "abcde";