Можно ли проверить, указывают ли два указателя на один и тот же объект?

#c #pointers

#c #указатели

Вопрос:

Давайте рассмотрим этот код:

 char arr[10];
char *ptr1 = amp;arr[0];
char *ptr2 = amp;arr[5];
 

или

 int i;
char *ptr1 = amp;i;
char *ptr2 = ptr1   1;
 

Очевидно, что эти два указателя указывают на один и тот же объект. Но есть ли какой-либо способ определить это впоследствии в коде? Возможно ли написать такую функцию?

 // Returns true if p1 and p2 points to the same object and false otherwise
bool same_object(void *p1, void *p2) {
    if(<condition>) 
        return true;
    return false;
}
 

Я подозреваю, что это невозможно, поскольку вы не можете получить размер массива только из указателя, но я хотел убедиться, что есть что-то, что я мог упустить из виду.

Комментарии:

1. Нет, не совсем. Все, что вы знаете из указателя, — это адрес, который он содержит в качестве своего значения. Ничего больше. Теперь, если вы знаете, где начинается и заканчивается объект, вы можете определить, указывают ли на него два указателя, но это противоположно возможности получения информации из самих указателей. (другими словами — «вы ничего не упускаете …» )

2. @DavidC.Rankin Я так и предполагал. Спасибо.

3. Для a char* » объектом «, на который он указывает, является a char , и эти два не указывают на один и тот же символ. Невозможно определить, указывают ли они на символы, которые являются частью одного и того же массива, без дополнительной информации.

4. Возможно (более или менее) объединение _Generic и sizeof получение смещения при условии, что первый аргумент всегда является началом объекта

Ответ №1:

Если вы не передаете адрес и размер объекта или не сохраняете их в переменных области видимости файла, то это невозможно.

Если вы передадите объект и его размер функции, то это будет вполне возможно. Что-то похожее на это четко определено для универсального объекта (независимо от того, скалярный, агрегатный, объединение):

 bool same_object (size_t         objsize, 
                  const uint8_t  obj [objsize], // pass any object cast to const uint8_t* here
                  const void*    p1, 
                  const void*    p2)
{
  uintptr_t start = (uintptr_t)obj;
  uintptr_t end   = start   objsize;
  uintptr_t i1    = (uintptr_t)p1;
  uintptr_t i2    = (uintptr_t)p2;

  return i1 >= start amp;amp; 
         i1 < end    amp;amp; 
         i2 >= start amp;amp; 
         i2 < end;
}
 

Предполагается, что экзотические системы не будут реализованы uint8_t , а обычные системы будут реализованы uint8_t как символьный тип.