Чтобы воссоздать эту небольшую проблему, я использую этот код (да, он был грубым и может быть уменьшен):
char hello[] = "John";
char *ptr1 = &hello[0];
char *ptr2 = &hello[1];
char *ptr3 = &hello[2];
char *ptr4 = &hello[3];
std::cout << ptr1 << "$";
std::cout << ptr2 << "$";
std::cout << ptr3 << "$";
std::cout << ptr4 << "$";
как вы можете видеть после попытки использования этого кода, он возвращает следующее:
John$ohn$hn$n$
Я понятия не имею, почему он принимает все элементы после указанного.
Любая помощь?
Это потому, что вы печатаете указатель, а не то, на что оно указывает. И указатели char
в программах на C часто указывают на начало char[]
который представляет строку '\0'
-terminated. Вот почему std::ostream
(из которого cout
является экземпляром) имеет перегруженный оператор <<
который выводит всю строку, вплоть до терминатора.
Чтобы напечатать только символ, сначала разыщите указатели:
std::cout << *ptr1 << "$";
Вместо этого вы можете использовать ссылки, которые рассматриваются в основном как замена самого значения:
char &ptr1 = hello[0];
Ваш вопрос, похоже, основан на некоторых совершенно необоснованных ожиданиях. Похоже, вы ожидали, что ваш код напечатает один символ для каждой строки cout <<...
Но почему вы ожидали этого? То, что вы отправляете cout
в свой код, на самом деле является указателем char *
. Почему вы ожидали, что cout
разыщет этот указатель для вас и напечатает символ? Ожидается, что будет выглядеть указатель на выходе (адрес), а не на значение символа.
Итак, вопрос, который вы действительно должны задавать, не "почему он печатает несколько символов из моего массива?". Вопрос, который вы действительно должны задавать, - "почему он печатает любого из моих персонажей вообще?". Вы никогда не разыменовали указатель. Однако вместо значения указателя вывод содержит последовательность объектов char
которые указывал указатель. Т.е., по-видимому, cout
решил разыграть ваш указатель для вас, даже если вы никогда явно не просили его об этом. Это вопрос, который вы должны задать: почему мой указатель получил разыменование?
И ответ заключается в том, что указатели [const] char *
получают специальное обращение при отправке в cout
с помощью оператора <<
. Там специально выделена перегруженная версия <<
оператора, введенная специально для этой цели. Эта версия оператора <<
будет обрабатывать указатели char *
как указывающие на начало строки C. И этот оператор будет выводить всю C-строку до нулевого символа-ограничителя. Это именно то, что происходит в вашем эксперименте.
Обратите внимание: если вы используете, например, любой другой тип указателя (например, int *
), вы не увидите заостренного значения (или значений) на выходе. Вы увидите представление, зависящее от реализации, самого указателя.
ptr1
через ptr4
также являются указателями на символы, поэтому <<
будет рассматривать их как строки и печатать их как таковые, давая вам то, что вы видели.
Если вам просто нужны символы в каждом месте, строки формы:
char ch1 = hello[0];
будет работать, так как изменит вывод на:
std::cout << *ptr1 << "$";
Я не совсем уверен, но если он cout получает указатель на char, он будет печатать все до тех пор, пока он не достигнет пробела в памяти (строка символов стиля C), и если вы просто хотите напечатать символ, вы должны напечатать только содержимое переменной, то есть просто передать содержимое, а не местоположение памяти...
если вы хотите напечатать значение на определенном адресе, то:
std::cout << *ptr1 << "$";
std::cout << *ptr2 << "$";
std::cout << *ptr3 << "$";
std::cout << *ptr4 << "$";