#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*
» объектом «, на который он указывает, является achar
, и эти два не указывают на один и тот же символ. Невозможно определить, указывают ли они на символы, которые являются частью одного и того же массива, без дополнительной информации.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
как символьный тип.