Хранение строки в массиве символов без нулевого символа

Я читаю C ++ Primer Plus от Стивена Прата. Он приводит этот пример:

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!

с комментарием, который:

Оба этих массива являются массивами char, но только вторая является строкой. Нулевой символ играет фундаментальную роль в строках в стиле C. Например, в C ++ есть много функций, которые обрабатывают строки, в том числе те, которые используются cout. Все они работают, обрабатывая строку символьно-символьно, пока не достигнут нулевого символа. Если вы попросите, чтобы cout отобразил красивую строку, такую как cat, в предыдущем примере, он отобразит первые семь символов, обнаружит нулевой символ и остановится. Но если вы достаточно неблагодарны, чтобы сказать cout для отображения массива dog из предыдущего примера, который не является строкой, cout печатает восемь букв в массиве, а затем продолжает проходить по памяти побайтно, интерпретируя каждый байт как символ для печати, пока он не достигнет нулевого символа. Поскольку нулевые символы, которые в действительности равны нулю байтами, имеют тенденцию быть общими в памяти, повреждение обычно быстро удерживается; тем не менее, вы не должны рассматривать массивы нестроковых символов как строки.

Теперь, если объявить мои переменные глобальными, вот так:

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

вывод будет:

abcdefgh12345678
12345678

Таким образом, действительно, cout «продолжает проходить по памяти побайтно», но только до конца второго символьного массива. То же самое происходит с любой комбинацией массивов символов. Я думаю, что все остальные адреса инициализированы в 0, и поэтому остановка cout. Это правда? Если я сделаю что-то вроде:

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

Я получаю в основном пустое место на выходе (например, 95%), но не везде.

Однако, если я объявлю, что мои массивы char немного короче, например:

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

оставляя все остальное таким же, я получаю следующий вывод:

abc
123

Теперь cout даже не проходит первый массив символов, не говоря уже о втором. Почему это происходит? Я проверил адреса памяти, и они последовательные, как в первом сценарии. Например,

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

дает

003B903C
003B9040

Почему поведение отличается в этом случае? Почему он не читает за пределами первого массива символов?

И, наконец, если я объявляю свои переменные внутри main, то я получаю поведение, предложенное Prata, а именно, много мусора печатается раньше, где-то достигается нулевой символ.

Я предполагаю, что в первом случае массив char объявлен в куче и что он инициализируется равным 0 (но не везде, почему?), А cout ведет себя по-разному в зависимости от длины массива char (почему?)

Я использую Visual Studio 2010 для этих примеров.

Ответы на вопрос(4)

Ваш ответ на вопрос