Armazenando uma string em uma matriz de caracteres sem o caractere nulo
Estou lendo o C ++ Primer Plus de Stephen Prata. Ele dá este exemplo:
char dog[8] = { 'b', 'e', 'a', 'u', 'x', ' ', 'I', 'I'}; // not a string!
char cat[8] = {'f', 'a', 't', 'e', 's', 's', 'a', '\0'}; // a string!
com o comentário que:
Ambas as matrizes são matrizes de char, mas apenas a segunda é uma string.O caractere nulo desempenha um papel fundamental em seqüências de caracteres de estilo C. Por exemplo, o C ++ tem muitas funções que manipulam cadeias de caracteres, incluindo aquelas usadas pelo cout.Todos eles trabalham processando uma cadeia caractere-por-caractere até que eles atinjam o caractere nulo. Se você perguntar ao cout para exibir uma string legal como cat no exemplo anterior, ele exibirá os sete primeiros caracteres, detectará o caractere nulo e será interrompido. Mas se você é desgracioso o suficiente para dizer ao cout para exibir o array de cães do exemplo anterior, que não é uma string, cout imprime as oito letras no array e então continua marcando byte de memória byte, interpretando cada byte como um byte. caractere a ser impresso, até atingir um caractere nulo. Como caracteres nulos, que são realmente definidos como zero, tendem a ser comuns na memória, o dano geralmente é contido rapidamente; no entanto, você não deve tratar matrizes de caracteres nonstring como strings.
Agora, se declarar minhas variáveis globais, assim:
#include <iostream>
using namespace std;
char a[8] = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'};
char b[8] = {'1', '2', '3', '4', '5', '6', '7', '8'};
int main(void)
{
cout << a << endl;
cout << b << endl;
return 0;
}
a saída será:
abcdefgh12345678
12345678
Então, de fato, o cout "continua marchando pela memória byte por byte", mas apenas até o final do segundo array de caracteres. A mesma coisa acontece com qualquer combinação de matriz de caracteres. Eu estou pensando que todos os outros endereços são inicializados para 0 e é por isso que o cout stop. Isso é verdade? Se eu fizer algo como:
for (int i = 0; i < 100; ++i)
{
cout << *(&a + i) << endl;
}
Estou obtendo principalmente espaço vazio na saída (como 95%, talvez), mas não em todos os lugares.
Se, no entanto, eu declarar meus arrays de char um pouco mais curtos, como:
char a[3] = {'a', 'b', 'c'};
char b[3] = {'1', '2', '3'};
mantendo todas as outras coisas iguais, estou recebendo a seguinte saída:
abc
123
Agora o cout nem passa do primeiro array de caracteres, sem mencionar o segundo. Por que isso está acontecendo? Eu verifiquei os endereços de memória e eles são seqüenciais, assim como no primeiro cenário. Por exemplo,
cout << &a << endl;
cout << &b << endl;
dá
003B903C
003B9040
Por que o comportamento é diferente neste caso? Por que não lê além do primeiro array de caracteres?
E, finalmente, se eu declarar minhas variáveis dentro do main, então eu obtenho o comportamento sugerido por Prata, ou seja, um monte de lixo é impresso antes, em algum lugar um caractere nulo é alcançado.
Eu estou supondo que no primeiro caso, a matriz char é declarada na pilha e que isso é inicializado para 0 (mas não em todos os lugares, por quê?) E cout se comporta de maneira diferente com base no comprimento da matriz char (por quê?)
Estou usando o Visual Studio 2010 para esses exemplos.