Гарантируется ли, что элементы массива C ++ находятся в непрерывных адресах? - PullRequest
3 голосов
/ 05 августа 2020

Другими словами, скажем, у меня есть массив объектов Object foo[10]

И функция принимает указатель на один из них в качестве аргумента: func(&foo[0])

Могу ли я чтобы получить доступ к остальной части массива внутри этой функции, вычислив эти смещения?

func(Object* a)
{
  Object* a0 = a;
  Object* a1 = a0 + sizeof(Object)
  Object* a2 = a0 + sizeof(Object)*2
}

Ответы [ 4 ]

8 голосов
/ 05 августа 2020

Да, элементы гарантированно будут смежными.

Но вам не нужно sizeof(Object). При добавлении числа к указателю это число автоматически умножается на размер типа, на который указывает указатель. Точно так же, когда вы вычитаете два указателя, результат делится на размер указанного типа.

Вы хотите это:

Object *a0 = a;
Object *a1 = a0 + 1;
Object *a2 = a0 + 2;
4 голосов
/ 05 августа 2020

From ссылочный сайт :

Объявление формы T a [N];, объявляет a как объект массива, состоящий из N смежных объектов типа T.

Также, в случае возникновения каких-либо вопросов ( определение объекта ):

Объект в C ++ является областью хранилище

Что касается косвенного обращения (нижний индекс), см. Встроенный оператор индексации

Встроенный индекс выражения E1 [E2] в точности идентично выражению * (E1 + E2)

3 голосов
/ 05 августа 2020

Нет, это не сработает. Когда вы выполняете арифметику c для указателей, это делается в единицах размера типа, на который он указывает. Так что вам не нужно умножать на sizeof(Object), это происходит автоматически; если вы сделаете это явно, вы умножитесь дважды.

Object *a0 = a; // points to a[0]
Object *a1 = a0 + 1; // points to a[1]
Object *a2 = a0 + 2; // points to a[2]

Вы умножите только на sizeof, если сначала приведете указатель к char *.

Object *a1 = (Object *)((char *)a0 + sizeof(Object));
Object *a2 = (Object *)((char *)a0 + sizeof(Object) * 2);
1 голос
/ 05 августа 2020

Гарантируется ли, что элементы массива C ++ находятся в смежных адресах?

Да.

Должен ли я получить доступ к остальной части массива внутри эта функция путем вычисления этих смещений?

Да. Фактически, это идиоматический c способ перебора элементов массива. Указатель на элемент массива - это итератор.

Object* a0 = a;
Object* a1 = a0 + sizeof(Object)
Object* a2 = a0 + sizeof(Object)*2

В этом примере a1 не будет указывать на следующего брата a0, если размер объекта не равен 1. Арифметика указателя c работает в единицах размер объекта, а не в байтах. Другими словами, чтобы получить указатель на следующий элемент, вы пишете a0 + 1. Чтобы получить сам элемент, вы можете объединить арифметику указателя c и косвенное обращение с помощью оператора индекса: a0[1].

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