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;

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.

questionAnswers(4)

yourAnswerToTheQuestion