Есть ли способ проверить, находится ли адрес памяти между двумя другими адресами?

#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;
    }
}

...
 

Онлайн-демонстрация