#c #pointers #iteration #memory-address
#c #указатели #итерация #memory-address
Вопрос:
Допустим, «гипотетически» у меня был этот код:
//two separate arrays of the same object that for the purposes of this question we will assume are not adjacent in memory
ObjectName* m_objects0 = new ObjectName[10];
ObjectName* m_objects1 = new ObjectName[10];
//and a pointer to a single object
ObjectName* m_pObject = nullptr;
Если бы я хотел перебирать каждый объект, m_objects0
пока не дойду до конца, а затем «перейти» к началу m_objects1
, чтобы перебрать его, как бы я проверил, находится ли адрес m_pObject
между начальным и конечным адресами любого массива? (моя единственная информация — это начальный и конечный адреса каждого массива) Возможно ли это вообще?
Единственный способ, которым я могу придумать, как это сделать, — это каким — то образом преобразовать адрес в int
.
Комментарии:
1. За исключением равенства / неравенства, вы можете сравнивать указатели только с указателями на элементы в том же массиве или члены того же класса. Итак, либо ваше сравнение показывает, что указатель находится в пределах массива, либо он имеет UB. Вы могли бы сравнить свой указатель с каждым элементом в одном из массивов, но это не кажется очень эффективным.
2. Какую цель высокого уровня вы пытаетесь достичь? Это звучит как проблема XY .
3. Кроме того, почему вы сравниваете низкоуровневые вещи, такие как адреса указателей? Хороший дизайн сравнивает, является ли какой-либо атрибут объекта одинаковым или существует в контейнере объектов, а не явно сравнивает адреса указателей, чтобы увидеть, попадает ли этот адрес «между» двумя адресами.
4. «как мне проверить, находится ли адрес
m_pObject
между начальным и конечным адресами любого массива» это не так, потому что это null . Или это не так, потому что это локальная переменная. В зависимости от того, что вы подразумеваете под «адресомm_pObject
«. Этот «гипотетический» сценарий может запутывать реальную проблему, которую вы пытаетесь решить.5. Вы не можете. Операторы
<
,<=
,>
, и>=
для указателей имеют неопределенное поведение, если оба указателя не указывают на элементы одного и того же массива или члены одной и той же структуры. Самое большее, что вы можете сделать, это проверить, указывает лиm_pObject
элемент на элементm_objects0
или он указывает на элементm_objects1
. Если он не указывает на элемент ни того, ни другого, вот и все — нет никакого способа (без вызова неопределенного поведения) проверить, указывает ли он «между» вашими массивами, «до» их обоих или «после» их обоих.
Ответ №1:
Вы можете проверить, равен ли данный указатель (in) любому другому указателю, используя операторы ==
and !=
.
Однако вы можете проверить, является ли данный указатель <(=)
или >(=)
другим указателем, только если оба указателя указывают на один и тот же объект / массив, в противном случае поведение не определено.
Итак, пока m_pObject
указывает на элемент в m_objects0
, вы не можете проверить, указывает ли он (не) m_objects1
на элемент при использовании диапазонов адресов.
Однако вместо этого вы можете сделать что-то вроде этого:
ObjectName* m_objects0 = new ObjectName[10];
ObjectName* m_objects1 = new ObjectName[10];
...
ObjectName* object_ptrs[] = {
m_objects0, m_objects0 10,
m_objects1, m_objects1 10
};
for(int i = 0; i < 4; i = 2)
{
ObjectName* m_pObject = object_ptrs[i];
ObjectName* m_pObjects_end = object_ptrs[i 1];
while (m_pObject != m_pObjects_end)
{
...
m_pObject;
}
}
...
Что, вы могли бы обобщить немного дальше (т. Е., Если вам нужно более 2 массивов), используя что-то это вместо:
#include <vector>
#include <utility>
ObjectName* m_objects0 = new ObjectName[10];
ObjectName* m_objects1 = new ObjectName[10];
...
std::vector<std::pair<ObjectName*,ObjectName*>> object_ptrs;
object_ptrs.emplace_back(m_objects0, m_objects0 10);
object_ptrs.emplace_back(m_objects1, m_objects1 10);
...
for(auto amp;p : object_ptrs)
{
ObjectName* m_pObject = p.first;
ObjectName* m_pObjects_end = p.second;
while (m_pObject != m_pObjects_end)
{
...
m_pObject;
}
}
...