Понимание строк как указателей в C++
У меня проблемы с пониманием строк как указателей. По-видимому, строка понимается как указатель, который указывает на первый адрес строки. Поэтому, используя оператор"&", я должен получить адрес первого символа строки. Вот небольшой пример:
#include "stdafx.h"
#include <iostream>
using namespace std;
int main(){
char text[101];
int length;
cout << "Enter a word: ";
cin >> text;
length = strlen(text);
for (int i = 0; i <= length; i++) {
cout << " " << &text[i];
}
return 0;
}
При вводе такого слова, как" Hello", выводится:"Hello ello llo lo o". Вместо этого я ожидал получить адрес каждого символа "Hello". Когда я использую гипс long(&text[i])
, он отлично работает. Но я этого не делаю. поймите почему. Без приведения, очевидно, оператор "& " - дает начальный адрес строки, которая будет напечатана. Используя приведение, он дает адрес каждого символа отдельно.
Может быть, СБ. можете мне это объяснить - я буду вам очень благодарен!
3 ответа:
Если у вас есть массив символов, хранящий строку, например
char text[] = "Hello";
Тогда массив инициализируется как
char text[] = { 'H', 'e', 'l', 'l', 'o', '\0' };
В этом утверждении
std::cout << text;
Используется
operator <<
перегруженный типconst char *
и массивtext
неявно преобразуется в указатель на его первый элемент.Вы могли бы написать вместо этого
std::cout << &text[0];
Потому что в обоих утверждениях выражения
text
и&text[0]
имеют типchar *
.Оператор перегружен для тип
const char *
выводит символы, начинающиеся с адреса в указателе, пока не встретится нулевой символ.Так что если вместо утверждения
std::cout << &text[0];
Ты напишешь
std::cout << &text[1];
Тогда единственное, что изменяется, - это начальный адрес строки и ничего больше. То есть фактически вы выводите строку, которая представлена как
{ 'e', 'l', 'l', 'o', '\0' }
Если написать
std::cout << &text[2];
То есть если указатель в правой части выражения сдвинут на единицу позиция справа означает, что вы будете иметь дело со строкой
{ 'l', 'l', 'o', '\0' }
И так далее.
То есть
operator <<
перегруженный какtemplate<class traits> basic_ostream<char, traits>& operator<<(basic_ostream<char, traits>&, const char*);
Просто выводит объекты, на которые указывает второй параметр, в виде строк.
Если вы хотите вывести значение самого указателя вместо строки, на которую указывает указатель, вы должны использовать другой перегруженный
operator <<
, объявленный какbasic_ostream<charT, traits>& operator<<(const void* p);
Tp вызвать его вы должны написать для пример
std::cout << ( void * )text;
Или
std::cout << ( void * )&text[i];
Где
i
- некоторый индекс.Вместо приведения C можно использовать приведение C++, например
std::cout << static_cast<void *>( &text[i] );
&text[i]
эквивалентноtext + i
и смещает указатель вдоль массиваchar[]
наi
места, используя арифметику указателя. Эффект состоит в том, чтобы начатьcout
на (i) - м Символе, с перегрузкой<<
вconst char*
вызывается. Это выводит все символы от начальной точки до нулевого Терминатора.
text[i]
однако это типchar
, и перегрузка<<
вchar
называется. Это выводит один символ.В C++, если вам нужна строка, то используйте
std::string
вместо этого. Вы все еще можете написатьcin >> text;
, Еслиtext
является типомstd::string
! Ваш код также не уязвим для переполнения буфераchar
.