Понимание строк как указателей в 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 2

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.

Чтобы вывести адрес элемента массива, можно сделать следующее:

cout << " " << (void*)&text[i];

Это:

cout << " " << &text[i];

Эквивалентно этому:

cout << " " << text + i;

Это означает, что вы просите вывести строку, начиная с индекса i.