Я хотел бы задать вопрос о указателях и массивах в C++.О указателях и массивах в C++
int a[10];
int *p1; p1 = &a[0];
int *p2; p2 = a;
int (*p3)[10]; p3 = &a;
В чем разница между p1, p2 и p3? Они очень сбивают с толку.
Я хотел бы задать вопрос о указателях и массивах в C++.О указателях и массивах в C++
int a[10];
int *p1; p1 = &a[0];
int *p2; p2 = a;
int (*p3)[10]; p3 = &a;
В чем разница между p1, p2 и p3? Они очень сбивают с толку.
Во-первых, a
представляет собой массив из 10 int
s. Это легкая часть.
p1
является «указателем на int
». Вы назначаете ему значение &a[0]
. Это берет адрес первого элемента a
. Таким образом, p1
теперь указывает на первый элемент a
.
p2
также является «указателем на int
». Вы назначаете a
прямо на него. В этом случае стандартное преобразование должно иметь место преобразованием array-to-pointer. В принципе, массив может быть преобразован в указатель на его первый элемент. Результат этого преобразования присваивается p2
. Таким образом, p2
является также указателем на первый элемент a
.
p3
является «указателем на массив из 10 int
». Вы берете адрес массива a
и присваиваете его этому указателю. Итак, теперь этот указатель указывает на сам массив (а не на первый его элемент).
Вы можете подумать: «Ну, первый элемент имеет тот же адрес, что и массив, так что в чем разница?» Фактически, вы заметите разницу при попытке увеличить указатель. Приращение p1
или p2
даст вам указатель на второй элемент массива. Приращение p3
даст вам указатель на следующий массив из 10 int
s (которого на самом деле не существует).
┌─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┐
│ int │ int │ int │ int │ int │ int │ int │ int │ int │ int │
└─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┘
^
└── p1, p2, p3
Так что, если вы начинаете с все указывает, как вы описали, а затем увеличивать их, вы получите:
┌─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬┄
│ int │ int │ int │ int │ int │ int │ int │ int │ int │ int │
└─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴┄
^ ^
└── p1, p2 └── p3
p1
указывает на первый элемент a
.
p2
вызывает a
, чтобы упасть в указатель на первый элемент, поэтому он также указывает на первый элемент a
.
p3
читается как указатель на массив из десяти целых чисел. Он указывает на a
, и приращение его будет двигаться вперед на sizeof(int) * 10
вместо sizeof(int)
.
Там нет никакой разницы между этими декларациями указателей. Все они указывают на первый элемент массива a [] (индекс 0). Они представляют собой только разные стили написания заявления.
И хотя он не существует, он действителен, чтобы увеличивать 'p3' один раз, поэтому проверка разности адресов для вас после его приращения в порядке и не будет вызывать неопределенное поведение. – chris
Hah, мне нравятся диаграммы :) – chris
Спасибо за помощь! Ваше объяснение в деталях, и диаграммы coooool! – redcap