В книге, которую я читаю, C ++ с нуля, на странице 113 автор создает массив символов:
myString[80];
Затем он использует функцию, которая копирует некоторые символы:
strcpy(myString,"Hello there");
Затем он создает указатель на массив:
*p1 = myString;
затем он использует смещение и присваивает значение этому смещению:
p1[4]='c';
мой вопрос, p1 является указателем, так что это адрес памяти, а смещение 4 дает ему адрес памяти на 4 пробела впереди, так что это означает, что он вводит букву ‘c’ в адрес памяти, а не в значение хранится по этому адресу. Не должно ли это быть:
*(p1[4])='c';
в общем, почему * (p1 + 4) нуждается в разыменовании, а p1 [4] — нет?
Я пытался понять это, и единственное, что могло иметь для меня смысл, — это если квадратные скобки действуют как звездочка для разыменования указателя. Это правильно или есть другая причина, почему p1 [4] не нужно разыменовывать?
Затем он создает указатель на массив:
*p1 = myString;
Предполагая, что под этим вы на самом деле имеете в виду, что p1
объявляется и инициализируется с помощью;
char *p1 = myString;
тогда ваша интерпретация неверна. p1
это указатель на char
не указатель на массив.
В этом определении myString
является (ранее объявленным в вашем вопросе) именем массива char
, В инициализации
char *p1 = myString;
имя myString
преобразуется в указатель Этот указатель будет иметь значение &myString[0]
(то есть адрес первого символа в myString
). Это значение, которое p1
получит.
Заявление
p1[4] = 'c';
затем установит пятый символ (поскольку индексация начинается с нуля) myString
быть 'c'
, Поэтому результат меняется myString[4]
к стоимости 'c'
, Это означает, что (первые 11 символов) myString
будет "Hellc there"
,
Исходя из вышесказанного, выражение *(p1[4])='c'
не будет компилироваться, т.к. (p1[4])
имеет тип char
и не может быть разыменовано с помощью *
оператор.
Семантически, в выражении p1[4]
эквивалентно *(p1 + 4)
, поскольку p1
инициализируется равным &myString[0]
, p1[4]
ТАКЖЕ эквивалентно обоим myString[4]
и к *(myString + 4)
,
Замечания: Если *(p1[4])='c'
был действителен в вашем коде, то p1[4] = 'c'
не будет действительным, что предполагает мое предположение об объявлении и инициализации p1
правильно — несмотря на то, что вы пропустили такую информацию.
p1 + 4
будет адрес памяти в 4 местах.
Выражение p1[4]
(точно эквивалентно *(p1+4)
) называется именующий выражение. Мы говорим, что выражение lvalue назначает в ячейка памяти. Или, другими словами, выражение lvalue является синонимом самой ячейки памяти. Вы всегда можете использовать &
оператор адреса в выражении lvalue, и это дает вам указатель на ячейку памяти.
Выражение lvalue будет использоваться одним из трех возможных способов:
Не существует специального синтаксиса, чтобы различать эти три случая; скорее это зависит от большего выражения, частью которого является выражение lvalue. Например, применяя &
оператор — это случай 3; появляется в левой части оператора присваивания =
это случай 1. Большинство других видов использования подпадают под случай 2.
p1[4]
рассматривается как *(p1 + 4)
который является «значением по смещению 4 от p1».
Также, когда вы объявляете массив символов:
myString[80]
myString — указатель на массив (он указывает на первый элемент). Итак, когда вы делаете myString[4]
это также рассматривается как *(myString + 4)
Пишу *(p1[4])
будет означать *(*(p1 + 4))