Я изучаю указатели, и я не понимаю, как указатели работают со строками в стиле C.
Почему эти два эквивалента?
char a[] = "Gme";
char* p = a; //Why am I allowed to assign "Gme" to a pointer (pointer is an address)
cout << p << " " << *(p+1); //Why does it print "gme" with "cout<<p" (I mean, I am printing an address)?
а также
char a[] = "Gme";
char* p = &a[0]; // How is this the same as char* p = a;
cout << p << " " << *(p+1);
В целом, я не понимаю, как указатели работают со строками. Как символы хранятся в памяти? Если мы рассматриваем строку как массив символов, почему я не могу напечатать адрес элемента символа?
Заранее спасибо 🙂
Это не имеет ничего общего с тем, что они являются строками в стиле C. Это верно для любого массива. Например, вы можете сделать:
int arr[10];
int* p = arr;
Причина, по которой вы можете это сделать, заключается в том, что существует стандартное преобразование, называемое массив к указателю преобразование. Это преобразует выражение, обозначающее массив (например, arr
выше), в указатель на его первый элемент. Мы знаем первый элемент arr
является int
поэтому указатель, который мы получаем из этого преобразования, является int*
,
char a[] = "Gme";
char* p = a;
В этом примере мы знаем a
это массив char
, Имеет 4 элемента: буквы G
, m
, e
и завершающий нулевой символ. Когда вы инициализируете p
с a
, вы выполняете преобразование массива в указатель, чтобы получить указатель на первый элемент массива. Первый элемент — это персонаж G
, так p
это указатель на этот символ.
std::cout
(и остальная часть стандартной библиотеки ввода / вывода) просто имеет специальные перегрузки, когда вы выводите char*
, Вместо того, чтобы просто печатать адрес, который содержит указатель, он предполагает, что указатель указывает на первый символ в строке с нулевым символом в конце (и обычно это правильно). Он получает каждую букву строки, просто увеличивая и разыменовывая указатель, который вы передали.
В целом, я не понимаю, как указатели работают со строками. Как символы хранятся в памяти?
Это большая тема, на которую уже дан ответ.
В чем разница между char s [] и char * s? хорошая отправная точка.
Если мы рассматриваем строку как массив символов, почему я не могу напечатать адрес элемента символа?
Вы можете. Вам просто нужно проделать дополнительную работу, чтобы уточнить компилятору, что именно вы хотите.
Есть перегрузка для <<
оператор что занимает ostream и char*
который интерпретирует правый операнд как NUL-концевую строку.
Если ты хочешь cout << ...
видеть только указатель p
, а не его тягучесть, затем приведение к void*
так что единственные опции, доступные диспетчеру вызова функции при выборе какой operator<<
перегрузка использовать те, которые воспринимают его как указатель.
C-String является массив который состоит из char
элементы.
Массив — это последовательность значений в памяти, которые не могут быть сохранены в одной переменной (поскольку переменные обычно имеют ограничение в 64 бита), поэтому переменная точки к первому элементу в массиве (например, содержит адрес первого элемента).
Так
голец a[] = "Gme"
создает массив, состоящий из «G», «m» и «e», сохраняет его в памяти, и a
содержит адрес первого элемента (в данном случае «G»).
char* p = a;
действует, потому что a
был неявно создан как указатель, поэтому вы просто присваиваете адрес первого элемента массива p.
char* p = &a[0];
допустимо, потому что [0] является значение в 0-м элементе a
, Добавляя &
Вы принимаете адрес 0-го элемента a
, Таким образом, р теперь указывает на первый элемент массива a
так что теперь p можно рассматривать как массив.