Почему указатель char автоматически разыменовывается в динамическом массиве

Возможно глупый вопрос. Когда я cout указал указатель на массив символов, я думал, что он напечатает адрес; вместо этого он разыменовывает адрес и печатает фактические значения до нуля.

В отличие от массива int, где он делает то, что я ожидаю. Он печатает адрес первого элемента.

Почему элемент char разыменовывается при печати указателя.

char* as = new char[100];
    as[0] = 'a';
    as[1] = 'b';
    as[2] = NULL;
    cout << as << endl;

    int* s = new int[100];
    s[0] = 2;
    cout << s << endl;

Спрашиваю об этом, потому что, когда я пытаюсь получить адрес первого элемента char a[0] = 'a';. Я должен хранить его в указателе на указатель. Что мне кажется странным, но это не главное.

char ** d = &as;
    cout << d << "this is d" << endl;

person Community    schedule 08.04.2015    source источник
comment
массивы символов = строки в стиле C. Система предполагает (в данном случае неправильно), что вы хотите распечатать саму строку, а не адрес строки.   -  person Marc B    schedule 08.04.2015
comment
@MarcB: Argh отвечает в комментариях -.-   -  person Lightness Races in Orbit    schedule 08.04.2015
comment
@LightningRacisinObrit О, извините, я думал, что вопрос в том, почему cout << d печатает строку ... и мне было интересно, как это происходит.   -  person Barry    schedule 08.04.2015
comment
stackoverflow.com/questions/501816/   -  person Giorgi Moniava    schedule 08.04.2015


Ответы (5)


Нет перегруженного оператора вывода <<, который печатает адрес для любого указателя char, он обрабатывает все указатели char как строки. Если вы хотите напечатать адрес указателя, вам нужно привести его к void*

std::cout << "Address of string is " << static_cast<void*>(as) << '\n';

Кстати, код

char ** d = &as;
cout << d << "this is d" << endl;

будет не печатать адрес строки, т. е. указатель, содержащийся внутри as, вместо этого он будет печатать место, где переменная as хранится в памяти. Не совсем то же самое.

person Some programmer dude    schedule 08.04.2015
comment
Итак, если бы я хотел сохранить адрес первого элемента. я бы все равно использовал char * as; но если я должен был напечатать его. я должен был бы ввести его? просто для уточнения - person ; 08.04.2015
comment
@tropicalmemes as сам по себе является указателем на первое место в памяти, которую вы выделили. И если вы хотите напечатать адрес, на который указывает as, вам нужно его привести. - person Some programmer dude; 08.04.2015
comment
@tropicalmemes: Да. - person Lightness Races in Orbit; 09.04.2015

Символьные указатели char* считаются строками в стиле C, оканчивающимися нулем, оператором std::ostream <<. Вы правы, что это поведение отличается от других типов указателей.

&a не является указателем на a[0] . Это указатель на a, который сам является указателем. a на самом деле является указателем на a[0] и эквивалентен &a[0].

person Brice M. Dempsey    schedule 08.04.2015
comment
@MooingDuck: модулем IOStreams стандартной библиотеки. - person Lightness Races in Orbit; 08.04.2015

IOStreams обрабатывает char*const char*) особым образом, так что вы можете печатать C-строки без дополнительных усилий:

std::cout << "hello world\n";

(Имейте в виду, что строковое литеральное выражение сразу же превращается в const char* при передаче в operator<<.)

Если вы не хотите такого поведения, вы можете привести к void*:

char* as = new char[100];
as[0] = 'a';
as[1] = 'b';
as[2] = NULL;
cout << (void*)as << endl;

Ваше «исправление» на самом деле не работает, потому что вы печатаете адрес указателя as, а не адрес элементов массива, на которые указывает as. На это указывает тип char**, который вы уже заметили.

person Lightness Races in Orbit    schedule 08.04.2015

Он печатает строку, потому что именно это делает определение этой конкретной operator<< перегрузки. Приведите к void *, если вы хотите напечатать адрес:

cout << static_cast<void *>(as) << endl;
person Carl Norum    schedule 08.04.2015

Оператор ‹‹ перегружен, чтобы принимать char* и выводить его содержимое, тогда как для int*/int[] такой перегрузки нет.

person NathanOliver    schedule 08.04.2015
comment
Нет, вывод &as не работает. Смотрите мой ответ. - person Lightness Races in Orbit; 08.04.2015