Almacenar una cadena en una matriz de caracteres sin el carácter nulo

Estoy leyendo el C ++ Primer Plus de Stephen Prata. Él da este ejemplo:

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!

con el comentario que:

Ambas matrices son matrices de char, pero solo la segunda es una cadena. El carácter nulo juega un papel fundamental en las cadenas estilo C. Por ejemplo, C ++ tiene muchas funciones que manejan cadenas, incluidas las utilizadas por cout. Todos trabajan procesando una cadena carácter por carácter hasta que alcanzan el carácter nulo. Si le pide a cout que muestre una buena cadena como cat en el ejemplo anterior, muestra los primeros siete caracteres, detecta el carácter nulo y se detiene. Pero si no tiene la gracia de decirle a cout que muestre la matriz de perros del ejemplo anterior, que no es una cadena, cout imprime las ocho letras de la matriz y luego sigue avanzando a través de la memoria byte por byte, interpretando cada byte como un Carácter a imprimir, hasta que alcance un carácter nulo. Debido a que los caracteres nulos, que en realidad son bytes establecidos en cero, tienden a ser comunes en la memoria, el daño generalmente está contenido rápidamente; no obstante, no debe tratar las matrices de caracteres sin cadenas como cadenas.

Ahora, si declaro mis variables globales, así:

#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;
}

La salida será:

abcdefgh12345678
12345678

Así que, de hecho, el cout "sigue marchando a través de la memoria byte por byte", pero solo hasta el final de la segunda matriz de caracteres. Lo mismo sucede con cualquier combinación de matriz char. Estoy pensando que todas las otras direcciones se inicializan a 0 y es por eso que cout se detiene. ¿Es esto cierto? Si hago algo como:

for (int i = 0; i < 100; ++i)
{
    cout << *(&a + i) << endl;
}

Estoy obteniendo mayormente espacio vacío en la salida (como el 95%, tal vez), pero no en todas partes.

Sin embargo, si declaro mis matrices de caracteres un poco más cortas, como:

char a[3] = {'a', 'b', 'c'};
char b[3] = {'1', '2', '3'};

manteniendo todas las otras cosas iguales, obtengo el siguiente resultado:

abc
123

Ahora el cout ni siquiera pasa la primera matriz de caracteres, por no mencionar la segunda. ¿Por qué está pasando esto? He comprobado las direcciones de memoria y son secuenciales, al igual que en el primer escenario. Por ejemplo,

cout << &a << endl;
cout << &b << endl;

da

003B903C
003B9040

¿Por qué el comportamiento es diferente en este caso? ¿Por qué no se lee más allá de la primera matriz de caracteres?

Y, por último, si declaro mis variables dentro de main, obtengo el comportamiento sugerido por Prata, es decir, se imprime mucha basura antes, en algún lugar se alcanza un carácter nulo.

Supongo que en el primer caso, la matriz char se declara en el montón y que esto se inicializa en 0 (pero no en todas partes, ¿por qué?) Y cout se comporta de manera diferente en función de la longitud de la matriz char (¿por qué?)

Estoy usando Visual Studio 2010 para estos ejemplos.

Respuestas a la pregunta(4)

Su respuesta a la pregunta