Почему я не могу изменить базовый адрес массива? Это потому, что выделенная память будет потеряна? в этом случае я могу создать массив с помощью указателя и изменить то, на что указывает указатель, и выделенная память тоже будет потеряна, тогда в чем разница?
Изменение базового адреса массива
Ответы (2)
Массивы сами по себе являются объектами, а не указателями. Рассмотрим более простой объект:
int a = 0;
Ожидаете ли вы, что сможете изменить его адрес? Конечно нет. Объект — это область хранения с типом. Регион хранения идентифицируется по его адресу, поэтому вы не ожидаете его изменения. И массивы тоже объекты. Когда вы объявляете
int b[8] = {0};
вы объявляете объект размером восемь целых чисел, который будет занимать некоторую память. Вы не можете изменить его адрес больше, чем вы можете изменить адрес любого отдельного int.
Вам, наверное, говорили, что массивы — это указатели. Но это не так! Чаще всего они могут быть преобразованы, даже неявно, в указатель, но они по-прежнему являются объектными типами. Указатели часто заменяют массивы, потому что адреса первого элемента достаточно, чтобы достичь любого другого элемента с помощью арифметики указателя, но указатель не является самим объектом массива. Разница становится очевидной, когда вы проверяете свойства их объектов. Например:
sizeof(b) != sizeof(int*)
Объект b
не имеет размера указателя, на самом деле он имеет размер 8 целых чисел, вероятно, больше указателя.
&b = foo;
сделал бы это. Это запрещено семантикой, в частности ограничением в C 2018 6.5.16 2: «Оператор присваивания должен иметь модифицируемое lvalue в качестве левого операнда».
- person Eric Postpischil; 17.06.2019
(int *arr)
. Функция может принимать только указатель. Передача массивов в качестве аргументов — это одно из мест, где происходят неявные преобразования, как я упоминал ранее.
- person StoryTeller - Unslander Monica; 19.06.2019
Адреса всех переменных предварительно вычисляются на разных этапах компиляции.
В сгенерированном коде вы можете видеть, что переменный объект заменен на
Static+k for static linkage
Stack+k for automatic linkage
Reg regname
Constant hardcoded
И это могут быть другие типы адресов.
Указатель — это объект, адрес которого предварительно вычисляется, как указано выше, но значение которого может быть переменной вышеуказанного типа.