Указатель арифметический замаскированный &(массив[0])
Сегодня я просмотрел некоторый исходный код (это был пример файла, объясняющий использование программного фреймворка) и обнаружил много кода, подобного этому:
int* array = new int[10]; // or malloc, who cares. Please, no language wars. This is applicable to both languages
for ( int* ptr = &(array[0]); ptr <= &(array[9]); ptr++ )
{
...
}
Таким образом, в основном, они сделали "взять адрес объекта, который лежит по адресу array + x
".
Обычно я бы сказал, что это просто глупость, так как написание array + 0
или array + 9
непосредственно делает то же самое. Я бы даже всегда переписывал такой код в size_t для цикла, но это вопрос стиля.
Но чрезмерное использование этого получило я думаю: не упускаю ли я чего-то явно очевидного или чего-то тонко скрытого в темных уголках языка?
Для тех, кто хочет взглянуть на исходный код, со всеми его неприятными goto
s, malloc
s и, конечно, эта указательная вещь, не стесняйтесь смотреть на него онлайн.
5 ответов:
Вы ничего не упускаете, они означают одно и то же.
Однако, чтобы попытаться пролить на это больше света, я должен сказать, что время от времени я также пишу подобные выражения для большей ясности. Я лично склонен мыслить в терминах объектно-ориентированного программирования, то есть предпочитаю ссылаться на "адресn
- го элемента массива", а не на "смещениеn
- го от начального адреса массива". Даже если эти две вещи эквивалентны в C, когда я пишу код, я имею в виду первое - поэтому я выражаю это. Возможно, так рассуждает и человек, написавший это письмо.
Да, для первого нет никаких веских причин. Это точно то же самое:
int *ptr = array;
Я согласен и со вторым, можно просто написать:
ptr < (array + 10)
Конечно, вы также можете просто сделать цикл
for
из 0-9 и установить указатель temp, чтобы он указывал на начало массива.Это, конечно, предполагает, чтоfor(int i = 0, *ptr = array; i < 10; ++i, ++ptr) /* ... */
ptr
не изменяется в теле цикла.
Edit: это частично неверно. Читать комментарии.
Проблема с
&(array[0])
заключается в том, что она расширяется до&(*(array + 0))
, Что включает разыменование. Теперь каждый компилятор, очевидно, оптимизирует это в то же самое, что иarray + 0
, но что касается языка, разыменование может вызвать UB в тех местах, гдеarray + 0
не будет.
Я думаю, что причина, по которой они написали это таким образом, заключалась в том, что
&(array[0])
И
&(array[9])
Просто выглядят похожими. Другим способом было бы написать его
array + 0
И
array + 9
Соответственно. Как вы уже упомянули, они по существу делают то же самое (по крайней мере, большинство компиляторов рассматривают его как то же самое, я надеюсь).
Два разных типа выражений можно интерпретировать по-разному: первое можно прочитать как "адрес элемента 0/9". Второй можно прочитать как "указатель массива со смещением элемента 0/9". Первый звучит более высокоуровнево, второй-более низкоуровнево. Однако большинство людей склонны использовать вторую форму. Теперь, посколькуarray + 0
, Конечно, то же самое, что иarray
, Вы можете просто написатьarray
. Я думаю, что дело здесь в том, что начало и конец цикла выглядят "аналогично" друг другу. Вопрос личного вкуса.
Согласно классической математике:
Array[n]
Относится кN-му элементу массива.
Чтобы "взять адрес" N-го элемента, применяется оператор
&
илиaddress of
:&Array[n]
Чтобы устранить любые предполагаемые неясности, добавляются скобки:
Для читателя, читающего слева направо, это выражение имеет смысл::&(Array[n])
возвращает адрес элемента в позиции ' n 'Страховка может иметь разработан в качестве защиты от старых неисправных компиляторов.
Некоторые люди считают его более читаемым, чем:
Array + n
Извините, но я старой школы и предпочитаю использовать версию"&", парен или без. Я буду тратить свое время на то, чтобы сделать код более легким для чтения, чем беспокоиться о том, какая версия занимает больше времени для компиляции или какая версия более эффективна.
Четко прокомментированный раздел кода имеет более высокую отдачу от инвестиций, чем раздел кода, который микро-оптимизирован для эффективности или использует разделы языка, которые незнакомы неязыковым юристам.