[c++] How to compare pointers?

Suppose I have 2 pointers:

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

If I want to compare them and see if they point at the same place does (a == b) work?

This question is related to c++ pointers

The answer is


To sum up. If we want to see if two pointers point to the same memory location we can do that. Also if we want to compare the contents of the memory pointed to by two pointers we can do that too, just remeber to dereference them first.

If we have

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

which are two pointers of the same type we can:

Compare memory address:

a==b

and compare contents:

*a==*b

Simple code to check pointer aliasing:

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

Output:

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

It depends on the types of the values, and the way that operators happen to have been defined. For example, string comparison is by value, not by address. But char * is by address normally (I think).

A big trap for the unwary. There is no guaranteed pointer comparison operator, but

  (void *)a == (void *)b 

is probably fairly safe.


The == operator on pointers will compare their numeric address and hence determine if they point to the same object.


Comparing pointers is not portable, for example in DOS different pointer values points to the same location, comparison of the pointers returns false.

/*--{++:main.c}--------------------------------------------------*/
#include <dos.h>
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
  int   val_a = 123;
  int * ptr_0 = &val_a;
  int * ptr_1 = MK_FP(FP_SEG(&val_a) + 1, FP_OFF(&val_a) - 16);

  printf(" val_a = %d -> @%p\n", val_a, (void *)(&val_a));
  printf("*ptr_0 = %d -> @%p\n", *ptr_0, (void *)ptr_0);
  printf("*ptr_1 = %d -> @%p\n", *ptr_1, (void *)ptr_1);

  /* Check what returns the pointers comparison: */
  printf("&val_a == ptr_0 ====> %d\n", &val_a == ptr_0);
  printf("&val_a == ptr_1 ====> %d\n", &val_a == ptr_1);
  printf(" ptr_0 == ptr_1 ====> %d\n",  ptr_0 == ptr_1);

  printf("val_a = %d\n", val_a);

  printf(">> *ptr_0 += 100;\n");
             *ptr_0 += 100;

  printf("val_a = %d\n", val_a);

  printf(">> *ptr_1 += 500;\n");
             *ptr_1 += 500;

  printf("val_a = %d\n", val_a);

  return EXIT_SUCCESS;
}
/*--{--:main.c}--------------------------------------------------*/

Compile it under Borland C 5.0, here is the result:

/*--{++:result}--------------------------------------------------*/
 val_a = 123 -> @167A:0FFE
*ptr_0 = 123 -> @167A:0FFE
*ptr_1 = 123 -> @167B:0FEE
&val_a == ptr_0 ====> 1
&val_a == ptr_1 ====> 0
 ptr_0 == ptr_1 ====> 0
val_a = 123
>> *ptr_0 += 100;
val_a = 223
>> *ptr_1 += 500;
val_a = 723
/*--{--:result}--------------------------------------------------*/

For a bit of facts here is the relevant text from the specifications

Equality operator (==,!=)

Pointers to objects of the same type can be compared for equality with the 'intuitive' expected results:

From § 5.10 of the C++11 standard:

Pointers of the same type (after pointer conversions) can be compared for equality. Two pointers of the same type compare equal if and only if they are both null, both point to the same function, or both represent the same address (3.9.2).

(leaving out details on comparison of pointers to member and or the null pointer constants - they continue down the same line of 'Do What I Mean':)

  • [...] If both operands are null, they compare equal. Otherwise if only one is null, they compare unequal.[...]

The most 'conspicuous' caveat has to do with virtuals, and it does seem to be the logical thing to expect too:

  • [...] if either is a pointer to a virtual member function, the result is unspecified. Otherwise they compare equal if and only if they would refer to the same member of the same most derived object (1.8) or the same subobject if they were dereferenced with a hypothetical object of the associated class type. [...]

Relational operators (<,>,<=,>=)

From § 5.9 of the C++11 standard:

Pointers to objects or functions of the same type (after pointer conversions) can be compared, with a result defined as follows:

  1. If two pointers p and q of the same type point to the same object or function, or both point one past the end of the same array, or are both null, then p<=q and p>=q both yield true and p<q and p>q both yield false.
  2. If two pointers p and q of the same type point to different objects that are not members of the same object or elements of the same array or to different functions, or if only one of them is null, the results of p<q, p>q, p<=q, and p>=q are unspecified.
  3. If two pointers point to non-static data members of the same object, or to subobjects or array elements of such members, recursively, the pointer to the later declared member compares greater provided the two members have the same access control (Clause 11) and provided their class is not a union.
  4. If two pointers point to non-static data members of the same object with different access control (Clause 11) the result is unspecified.
  5. If two pointers point to non-static data members of the same union object, they compare equal (after conversion to void*, if necessary). If two pointers point to elements of the same array or one beyond the end of the array, the pointer to the object with the higher subscript compares higher.
  6. Other pointer comparisons are unspecified.

So, if you had:

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

Also OK:

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

But it depends on the something in your question:

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
}

Bonus: what else is there in the standard library?

§ 20.8.5/8: "For templates greater, less, greater_equal, and less_equal, the specializations for any pointer type yield a total order, even if the built-in operators <, >, <=, >= do not."

So, you can globally order any odd void* as long as you use std::less<> and friends, not bare operator<.