Почему `& array` и` array` указывают на один и тот же адрес? - PullRequest
0 голосов
/ 21 февраля 2019

До сих пор я думал, что массив такой же, как указатель.Но я обнаружил странный случай:

код

int array[5] = { 10,11,12,13,14};

std::cout << array << std::endl;
std::cout << &array << std::endl;
std::cout << &array[0] << std::endl;

int *pArray = new int[5];

std::cout << pArray << std::endl;
std::cout << &pArray << std::endl;
std::cout << &pArray[0] << std::endl;

output

0x7ffeed730ad0
0x7ffeed730ad0
0x7ffeed730ad0

0x7f906d400340
0x7ffeed730a30
0x7f906d400340

Как видите, array и &array имеют одинаковое значение.Но pArray и &pArray имеют разное значение.Если массив совпадает с указателем, адрес массива должен отличаться от массива.Как array и &array могут быть одинаковыми?Если array и &array одинаковы, каков адрес памяти, в которой хранятся значения массива?

Ответы [ 2 ]

0 голосов
/ 21 февраля 2019

Массив X должен вести себя как указатель на непрерывный список X в памяти, так же, как указатель.Однако нигде не написано, где память, в которой хранятся эти данные, должна иметь собственный адрес и возможность записи.В случае явного указателя существует новое выделение для этого адреса (в данном случае стека), однако для массива в стеке компилятор уже знает, где находится содержимое, поэтому новое выделение не требуется.

Как следствие, небезопасно рассматривать его как указатель без индексации.например:

pArray = nullptr; // This is a memory leak, unless a copy is taken, but otherwise fine.
array = nullptr; // This is will make the compiler upset
0 голосов
/ 21 февраля 2019

Обычный array распадается на указатель на свой первый элемент, он равен &array[0].Первый элемент также начинается с того же адреса, что и сам массив.Следовательно &array == &array[0].

Но важно отметить, что типы различны:

  • Тип &array[0] (в вашем примере) int*.
  • Тип &array имеет вид int(*)[5].

Соотношение между &array[0] и &array может быть проще, если я покажу его немного подробнее "графически "(с добавленными указателями):

+----------+----------+----------+----------+----------+
| array[0] | array[1] | array[2] | array[3] | array[4] |
+----------+----------+----------+----------+----------+
^
|
&array[0]
|
&array

В качестве дополнительного приложения array распадается на указатель на свой первый элемент, то есть array распадается на &array[0] и, следовательно, будет иметь то же самоеtype.


Однако с указателями все иначе.Указатель pArray указывает на некоторую память, значение pArray - это местоположение этой памяти.Это то, что вы получаете, когда используете pArray.Это также то же самое, что и &pArray[0].

Когда вы используете &pArray, вы получаете указатель на указатель .То есть вы получаете местоположение (адрес) самой переменной pArray.Его тип int**.

Несколько графически с указателем pArray это будет примерно так:

+--------+       +-----------+-----------+-----------+-----------+-----------+-----+
| pArray | ----> | pArray[0] | pArray[1] | pArray[2] | pArray[3] | pArray[4] | ... |
+--------+       +-----------+-----------+-----------+-----------+-----------+-----+
^                ^
|                |
&pArray          &pArray[0]

[Обратите внимание на ... в конце«массив», потому что указатели не сохраняют информацию о памяти, на которую он указывает.Указатель указывает только на определенное место, «первый» элемент «массива».Обрабатывать память как «массив» - дело программиста.]

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...