Понимание справочника char

Я написал этот простой script, чтобы понять, что такое ссылка, и я зацикливаюсь на массиве char.

int numbers[5] = {3, 6, 9, 12, 15};

for (int i = 0; i < 5; i++)
{
    cout << numbers[i] << endl;
    cout << &numbers[i] << endl;
}

cout << "--------------" << endl;

char letters[5] = {'a', 'b', 'c', 'd', 'e'};

for (int i = 0; i < 5; i++)
{
    cout << letters[i] << endl;
    cout << &letters[i] << endl;
}

и это результат:

3
0xbffff958
6
0xbffff95c
9
0xbffff960
12
0xbffff964
15
0xbffff968
--------------
a
abcde
b
bcde
c
cde
d
de
e

С массивом int, когда я использую &numbers[i], я получаю странное число, которое является ячейкой памяти. Хорошо; это именно то, что я понял.

Но с char я не понимаю, почему у меня этот вывод.

Ответ 1

Причина в том, что cout "знает", что делать со значением char * - он печатает символьную строку как строку C с завершающим NUL.

То же самое не относится к значению int *, поэтому cout вместо этого выводит значение указателя.

Вы можете принудительно выводить значение указателя путем кастинга:

cout << static_cast<void *>(&letters[i]) << endl;

Ответ 2

Вы смотрите на особенности потоков С++. Он пытается преобразовать свои аргументы в то, что обычно печатается. Тип этого выражения &ints[x] int*. &chars[x] становится char*, который, кстати, также является типом символьной строки C. Поскольку мы хотим, чтобы этот cout << "FOO"' распечатывал всю строку, необходимо иметь такое поведение. В вашем случае это фактически приводит к поведению undefined, так как строка, которую вы используете, не имеет нулевого завершения. Для решения этой проблемы используйте static_cast.

Ответ 3

Когда вы переходите к ostream::operator<< (на самом деле это глобальная функция, а не оператор) аргумент типа char*, он рассматривается как строка с завершающим нулем.