Как сравнить указатели? - PullRequest
67 голосов
/ 01 февраля 2012

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

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

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

Ответы [ 6 ]

91 голосов
/ 01 февраля 2012

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

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

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

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

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

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

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

Самое «заметное» предостережение связано с виртуалами, и это тоже логично ожидать:

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

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

С § 5.9 C ++Стандарт 11:

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

  1. Если два указателя pи q одного и того же типа указывают на один и тот же объект или функцию, или оба указывают один за концом одного и того же массива, или оба равны null, тогда p<=q и p>=q оба дают истину и p<q и p>qоба дают false.
  2. Если два указателя p и q одного и того же типа указывают на разные объекты, которые не являются членами одного и того же объекта или элементов одного и того же массива или на разные функции, илиесли только один из них является нулевым, результаты p<q, p>q, p<=q, и p>=q не определены .
  3. Если два указателя указывают на нестатические элементы данныхтот же объект, или подобъектам или элементам массива таких членов, рекурсивно, указатель на объявленную позже мембрануr сравнивает большее, если два члена имеют одинаковый контроль доступа (пункт 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_equal и less_equal, специализации для любого типа указателя дают общий порядок, даже если встроенные операторы <, >, <=, >= не делают. "

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

57 голосов
/ 01 февраля 2012

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

19 голосов
/ 01 февраля 2012

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

13 голосов
/ 01 февраля 2012

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

Если у нас есть

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

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

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

a==b

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

*a==*b
1 голос
/ 21 декабря 2018

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

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
0 голосов
/ 01 февраля 2012

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

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

Вы знаете адрес что-то1, которое является & что-то1. Также адресом что-то2 является & чем-то2.

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

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...