Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pointer values are different but they compare equal. Why?

A short example outputs a weird result!

#include <iostream>  using namespace std;  struct A { int a; };     struct B { int b; }; struct C : A, B {     int c; };  int main() {     C* c = new C;     B* b = c;      cout << "The address of b is 0x" << hex << b << endl;     cout << "The address of c is 0x" << hex << c << endl;      if (b == c)     {         cout << "b is equal to c" << endl;     }     else     {         cout << "b is not equal to c" << endl;     } } 

It's very surprising to me that the output should be as follows:

The address of b is 0x003E9A9C The address of c is 0x003E9A98 b is equal to c 

What makes me wonder is:

0x003E9A9C is not equal to 0x003E9A98, but the output is "b is equal to c"

like image 704
xmllmx Avatar asked Aug 16 '13 12:08

xmllmx


People also ask

Is it possible to compare two pointers Why?

We can compare pointers if they are pointing to the same array. Relational pointers can be used to compare two pointers. Pointers can't be multiplied or divided.

What does it mean when two pointers are equal?

Equality operator (==,!=) 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). [...]

Can you compare pointers of different types?

When two pointers are compared, the result depends on the relative locations in the address space of the objects pointed to. If two pointers to object types both point to the same object, or both point one past the last element of the same array object, they compare equal.

What happens when you set pointers equal to each other?

3) Pointer Assignment Pointer assignment between two pointers makes them point to the same pointee. So the assignment y = x; makes y point to the same pointee as x . Pointer assignment does not touch the pointees. It just changes one pointer to have the same reference as another pointer.


2 Answers

A C object contains two sub-objects, of types A and B. Obviously, these must have different addresses since two separate objects can't have the same address; so at most one of these can have the same address as the C object. That is why printing the pointers gives different values.

Comparing the pointers doesn't simply compare their numeric values. Only pointers of the same type can be compared, so first one must be converted to match the other. In this case, c is converted to B*. This is exactly the same conversion used to initialise b in the first place: it adjusts the pointer value so that it points to the B sub-object rather than the C object, and the two pointers now compare equal.

like image 97
Mike Seymour Avatar answered Sep 19 '22 13:09

Mike Seymour


The memory layout of an object of type C will look something like this:

|   <---- C ---->   | |-A: a-|-B: b-|- c -| 0      4      8     12 

I added the offset in bytes from the Address of the object (in a platform like yours with sizeof(int) = 4).

In your main, you have two pointers, I'll rename them to pb and pc for clarity. pc points to the start of the whole C object, while pb points to the start of the B subobject:

   |   <---- C ---->   |    |-A: a-|-B: b-|- c -|    0      4      8     12 pc-^   pb-^ 

This is the reason why their values are different. 3E9A98+4 is 3E9A9C, in hex.

If you now compare those two pointers, the compiler will see a comparison between a B* and a C*, which are different types. So it has to apply an implicit conversion, if there is one. pb cannot be converted into a C*, but the other way round is possible - it converts pc into a B*. That conversion will give a pointer that points to the B subobject of wherever pc points to - it is the same implicit conversion used when you defined B* pb = pc;. The result is equal to pb, obviously:

   |   <---- C ---->   |    |-A: a-|-B: b-|- c -|    0      4      8     12 pc-^   pb-^    (B*)pc-^ 

So when comparing the two pointers, the compiler in fact compares the converted pointers, which are equal.

like image 23
Arne Mertz Avatar answered Sep 17 '22 13:09

Arne Mertz