Cout << с char * аргумент печатает строку, а не значение указателя
Это:
const char * terry = "hello";
cout<<terry;
выводит hello
вместо адреса памяти 'h'
. Почему это происходит?
Ответы
Ответ 1
Причиной этого является то, что std::cout
будет обрабатывать char *
как указатель на (первый символ) строки стиля C и печатать его как таковой. Если вы хотите вместо этого адрес, вы можете просто передать его указателю, который не обрабатывается таким образом, например:
cout << (void *) terry;
(или используйте приведение const void *
, если вы беспокоитесь о том, чтобы покинуть конспирацию, что не является проблемой в данном конкретном случае).
Если вы скорее пурист, чем прагматик, вы также можете использовать С++ static_cast
в соответствии с строками:
cout << static_cast <const void *> (terry);
хотя в этом конкретном случае это необязательно, приведение к void *
будет работать нормально. Следующий пример кода показывает все эти параметры в действии:
#include <iostream>
int main (void) {
const char *terry = "hello";
std::cout << terry << '\n';
std::cout << (void *) terry << '\n';
std::cout << (const void *) terry << '\n';
std::cout << static_cast<const void *> (terry) << '\n';
return 0;
}
(адрес может быть другим в вашей среде):
hello
0x8048870
0x8048870
0x8048870
Обратите внимание, что при использовании static_cast
вы должны убедиться, что не пытаетесь отбросить константу с помощью static_cast <void *>
(для чего предназначен const_cast
). Это одна из проверок, выполненных более новыми С++-переходами, и старинный стиль не имеет этого ограничения.
Ответ 2
Оператор <<
на std::cout
перегружен. Его поведение зависит от типа правильного операнда. (На самом деле это несколько разных функций, все они называются operator<<
, компилятор решает, какой из них вызывать.)
Если вы даете ему char*
или const char*
, он обрабатывает операнд как указатель на (первый символ) строки стиля C и печатает содержимое этой строки:
const char * terry = "hello";
cout << terry; // prints "hello"
Если вы даете ему значение char
, оно печатает это значение как символ:
cout << *terry; // prints "h"
cout << terry[0]; // the same
Если вы указали ему указатель типа void*
, он печатает это значение указателя (в определенном варианте реализации, обычно шестнадцатеричном):
cout << static_cast<const void*>(terry); // prints something like 0x4008e4
Рассмотрение char*
или const char*
в качестве указателя на строку C-стиля - это особый случай, и единственное, что я могу придумать, которое вызывает operator<<
для печати чего-либо, кроме значения операнд. Причина этого восходит к корням С++ в C, который не имеет типа "string" и манипулирует строками с помощью указателей char*
.
Существует множество других перегрузок для operator<<
для различных целых чисел и числовых типов с плавающей запятой для std::string
и т.д.
Ответ 3
Вы должны изменить свой код на это:
cout << static_cast<const void*>(terry);
Проблема заключается в том, что оператор <<
перегружен для указателей на строки C-стиля для печати содержимого строки. Если вместо этого вы нарисуете его на необработанный указатель, вы будете использовать поведение указателя печати по умолчанию, используя iostreams, как вы хотите.
Ответ 4
cout
перегружен, поэтому, когда вы даете ему char*
, он будет печататься как указатель на строку в стиле C. Таким образом, он печатает символы, пока не достигнет нулевого завершающего символа.
Если вы используете printf
вместо cout
, вы увидите адрес. Вы также можете привести указатель к другому типу, скажем, (void*)
, и вы также получите адрес.
Ответ 5
std::cout
определяется как std::ostream
с этим определением operator<<
.
В частности, эта строка:
template< class CharT, class Traits >
basic_ostream<CharT,Traits>& operator<<( basic_ostream<CharT,Traits>& os,
const char* s );
Это выбирается, когда вы используете <<
с аргументом типа char*
.
Случай с любым другим типом указателя, отличного от символа, приводится здесь:
basic_ostream& operator<<( const void* value );
Это продолжается до std::num_put
, который предназначен для форматирования числовых значений. Поэтому указатель численно интерпретируется как %p
в функциях форматирования C.
Ответ 6
"hello" - это строка, т.е. массив char. const char*
является указателем на этот массив, поэтому, когда вы разыскиваете этот указатель, вы получаете значение первого элемента.
Это похоже на
int a[] = {1, 2, 3};
int *b = a;
cout << *b << endl;
вы получите только 1
.