Этот код:
string str1 ( "Hello world" );
const char *c_str1 = str1.c_str ( );
cout << "The C-style string c_str1 is: " << c_str1
генерирует этот вывод:
The C-style string c_str1 is: Hello world
и я этого не понимаю.
c_str1
это указатель, верно? Так, c_str1
должен вернуть адрес и только *c_str1
должен дать значение, расположенное по этому адресу. Однако в приведенном выше примере c_str1
дает значение (не адрес).
Что я неправильно понимаю?
Это из-за того, как std::cout::operator <<
определяется — он имеет перегрузку, которая принимает const char*
и печатает строку, на которую он указывает. Если вы хотите адрес, вам нужно будет void*
,
«Что я неправильно понимаю?» Определение <<
на char
, Указатель передается по значению, но определение
const*
operator<<( std::ostream&, char const* )
указывает, что это
рассматривать указатель как начало '\0'
завершенная строка.
Переменная c_str1
указатель на первый символ в строке &c_str1
это указатель на c_str1
(то есть указатель на указатель). *c_str1
это значение в месте, указанном c_str1
(т.е. только один символ).
Оператор вывода имеет перегрузку, которая принимает указатель на символ (что c_str1
есть) и печатает его в виде строки.
Стандарт определяет перегрузки operator<< (ostream, char*)
которые выводят строку, хранящуюся в указателе. Другими словами, c_str1
это действительно указатель, но выходной поток интерпретирует его как строку, на которую он указывает.
Чтобы вывести значение указателя, приведите его к void*
:
cout << "The C-style string c_str1 is: " << static_cast<void*>(c_str1);
Есть перегрузка ostream& operator<<
за const char*
, который предполагает, что указатель указывает на первый символ в строка с нулевым символом в конце, и печатает всю строку.
Вы можете увидеть пример применения этого предположения где-то, чего не должно быть здесь:
#include <iostream>
int main()
{
char c = 'x'; // not a null terminated string
std::cout << &c << std::endl; // will write until it finds a 0 (really UB)
}
Оператор Cout<< интерпретирует указатели на char как C-строки.