Подтвердить что ты не робот

Cout << с char * аргумент печатает строку, а не значение указателя

Это:

const char * terry = "hello";
cout<<terry;

выводит hello вместо адреса памяти 'h'. Почему это происходит?

4b9b3361

Ответ 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.