Как сравнить указатели?

Предположим, что у меня есть 2 указателя:

int *a = something;
int *b = something;

Если я хочу их сравнить и посмотреть, указывают ли они на одно и то же место (a == b)?

Ответ 1

Да, это определение равенства указателя: они оба указывают на одно и то же местоположение (или псевдонимы указателя)

Ответ 2

Для небольшого количества фактов вот соответствующий текст из спецификаций

Оператор равенства (==,! =)

Указатели на объекты одного типа можно сравнить на равенство с "интуитивными" ожидаемыми результатами:

Из § 5.10 стандарта С++ 11:

Указатели одного типа (после преобразования указателей) можно сравнивать на равенство. Два указателя одного типа сравниваются равными, если и только если они оба равны нулю, оба указывают на одну и ту же функцию или оба представляют один и тот же адрес (3.9.2).

(опуская детали сравнения указателей на член и/или константы нулевого указателя - они продолжают в той же строке "Делай, что я имею в виду" :)

  • [...] Если оба операнда равны нулю, они сравниваются одинаково. В противном случае, если только один равен нулю, они сравниваются неравно. [...]

Самое "бросающееся в глаза" предостережение связано с виртуальными машинами, и, похоже, это тоже логично:

  • [...] если любой из них является указателем на виртуальную функцию-член, результат не указан. В противном случае они сравниваются равными, если и только если они ссылались бы на один и тот же член того же самого производного объекта (1.8) или того же подобъекта, если на них была разыменована гипотетический объект связанного типа класса. [...]

Реляционные операторы (<,>, <=,> =)

Из п. 5.9 стандарта С++ 11:

Указатели на объекты или функции одного и того же типа (после преобразования указателей) можно сравнить с результатом, определяемым следующим образом:

  1. Если два указателя p и q одного и того же типа указывают на один и тот же объект или функцию, или оба указывают один за концом одного и того же массива, или оба равны нулю, то p<=q и p>=q оба дают истину и p<q и p>q оба дают ложь.
  2. Если два указателя p и q одного и того же типа указывают на разные объекты, которые не являются членами одного и того же объекта или элементов одного и того же массива или на разные функции, или если только один из них имеет значение null, результаты p<q, p>q, p<=q, и p>=q не определены.
  3. Если два указателя указывают на нестатические элементы данных одного и того же объекта или субобъекты или элементы массива таких элементов, рекурсивно, указатель на объявленный позже элемент сравнивается больше, если два элемента имеют одинаковый контроль доступа (раздел 11) и при условии, что их класс не является союзом.
  4. Если два указателя указывают на нестатические элементы данных одного и того же объекта с разным контролем доступа (пункт 11), результат не уточняется.
  5. Если два указателя указывают на нестатические элементы данных одного и того же объекта объединения, они сравниваются равными (после преобразования в void*, если необходимо). Если два указателя указывают на элементы одного и того же массива или один за концом массива, указатель на объект с более высоким индексом сравнивается выше.
  6. Другие сравнения указателей не определены.

Итак, если у вас было:

int arr[3];
int *a = arr;
int *b = a + 1;
assert(a != b); // OK! well defined

Также хорошо:

struct X { int x,y; } s;
int *a = &s.x;
int *b = &s.y;
assert(b > a); // OK! well defined

Но это зависит от того, something в вашем вопросе:

int g; 
int main()
{
     int h;
     int i;

     int *a = &g;
     int *b = &h; // can't compare a <=> b
     int *c = &i; // can't compare b <=> c, or a <=> c etc.
     // but a==b, b!=c, a!=c etc. are supported just fine
}

Бонус: что еще есть в стандартной библиотеке?

§ 20.8.5/8: "Для шаблонов" greater, less, greater, greater_equal и less_equal, специализации для любого типа указателя дают полный порядок, даже если встроенные операторы <, >, <=, >= не делают".

Таким образом, вы можете глобально заказать любой нечетный void* если используете std::less<> и friends, а не bare operator<.

Ответ 3

Оператор == на указателях будет сравнивать их числовой адрес и, следовательно, определить, указывают ли они на один и тот же объект.

Ответ 4

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

Если мы имеем

int *a = something; 
int *b = something;

которые являются двумя указателями того же типа, мы можем:

Сравнить адрес памяти:

a==b

и сравните содержимое:

*a==*b

Ответ 5

Простой код для проверки псевдонимов указателей:

int main () {
    int a = 10, b = 20;
    int *p1, *p2, *p3, *p4;

    p1 = &a;
    p2 = &a;
    if(p1 == p2){
        std::cout<<"p1 and p2 alias each other"<<std::endl;
    }
    else{
        std::cout<<"p1 and p2 do not alias each other"<<std::endl;
    }
    //------------------------
    p3 = &a;
    p4 = &b;
    if(p3 == p4){
        std::cout<<"p3 and p4 alias each other"<<std::endl;
    }
    else{
        std::cout<<"p3 and p4 do not alias each other"<<std::endl;
    }
    return 0;
}

Выход:

p1 and p2 alias each other
p3 and p4 do not alias each other

Ответ 6

Допустим, вы должны указать указатели:

int *a = something1;
int *b = something2;

Вы знаете адрес something1, который является & something1. Также адрес чего-то2 есть & something2.

Итак, что вам нужно сделать, это проверить, правильно ли указаны два адреса, на которые указывают указатели.

чтобы вы использовали что-то вроде

if(&something1 == &something2) {
//do something
}

или вы можете использовать оператор ==, чтобы проверить, имеет ли указатель a равное значение с указателем b.