Я нашел коды, которые используют оператор адреса для адреса. См. ниже примеры кодов.
int arr[4] = { -1, -1, -1, -1 };
int arr2[4] = { 0, 0, 0, 0 };
memcpy(arr, &arr2, sizeof(arr2)); // & operator to arr2
Когда я проверяю значения (arr, &arr) с помощью printf, оба адреса равны.
И я понятия не имею, почему эти коды действительны. (я использую С++ 14)
Массивы естественным образом распадаются на указатели на их первый элемент. Так, например. arr
совпадает с &arr[0]
и имеет тип int *
. То же самое при использовании простого arr2
. Но &arr2
является указателем на сам массив и будет иметь тип int (*)[4]
, что действительно несовместимо с типом int *
. С учетом сказанного, и &arr[0]
, и &arr
«к счастью» оказались в одном и том же месте.
Краткий ответ - потому что язык позволяет это
Также обратите внимание, что из-за распада массива на указатель очень сложно передавать массивы функциям. В качестве аргумента объявление int arr[]
(или даже использование такого размера, как int arr[4]
) рассматривается как int *arr
. Если вы затем используете оператор указателя на переменную-аргумент, вы получите указатель на эту переменную (имеющую тип int **
), а не на исходный массив.
И в С++, пожалуйста, не используйте простые массивы, если вы можете этого избежать. Если размер фиксирован и известен во время компиляции (и не слишком велик), используйте std::array
(как в std::array<int, 4>
). В противном случае используйте std::vector
. Это решит множество проблем, с которыми вы можете столкнуться при использовании простых массивов в стиле C.
Эти ответы ясны и полезны. Спасибо за ответы и дополнительные пояснения!
Почему я могу использовать адрес адреса без каких-либо ошибок?
Потому что std::memcpy
принимает аргументы типа void*
(кроме квалификатора const), а все указатели на объекты неявно преобразуются в void*
.
Хотя arr
сам по себе не является указателем, это массив, а массивы неявно преобразуются в указатель на первый элемент, который неявно преобразуется в void*
.
&arr2
— это указатель на массив, который неявно преобразуется в void*
.
Когда я проверяю значения (arr, &arr) с помощью printf, оба адреса равны.
Место в памяти первого элемента массива совпадает с местом в памяти массива.
&arr2
— адрес массива в целом.arr2
сам по себе распадается на адрес первого элемента массива. Бывает так, что массив и его первый элемент находятся по одному и тому же адресу.