一个简短的例子会输出一个奇怪的结果!
#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;
}
}输出结果如下:,这让我非常惊讶。
The address of b is 0x003E9A9C
The address of c is 0x003E9A98
b is equal to c让我好奇的是:
0x003E9A9C不等于0x003E9A98,但输出为"b is equal to c"
发布于 2013-08-16 20:12:08
C对象包含两个子对象,类型分别为A和B。显然,它们必须有不同的地址,因为两个不同的对象不能有相同的地址;所以它们中最多有一个可以与C对象有相同的地址。这就是为什么打印指针会产生不同的值。
比较指针并不是简单地比较它们的数值。只能比较相同类型的指针,因此必须转换第一个指针以匹配另一个指针。在本例中,c被转换为B*。这与最初用于初始化b的转换完全相同:它调整指针值,使其指向B子对象而不是C对象,并且两个指针现在比较相等。
发布于 2013-08-16 20:21:13
类型为C的对象的内存布局如下所示:
| <---- C ----> |
|-A: a-|-B: b-|- c -|
0 4 8 12我以字节为单位添加了与对象地址的偏移量(在类似您的平台中,sizeof(int) = 4)。
在main中,您有两个指针,为清楚起见,我将它们重命名为pb和pc。pc指向整个C对象的开始,而pb指向B子对象的开始:
| <---- C ----> |
|-A: a-|-B: b-|- c -|
0 4 8 12
pc-^ pb-^这就是为什么他们的价值观不同的原因。3E9A98+4是3E9A9C,十六进制。
如果现在比较这两个指针,编译器将看到B*和C*之间的比较,这是不同类型的指针。因此,如果有隐式转换,它必须应用隐式转换。pb不能转换为C*,但反过来也是可能的-它将pc转换为B*。该转换将给出一个指针,该指针指向pc所指向的任何位置的B子对象-这与定义B* pb = pc;时使用的隐式转换相同。显然,结果等于pb:
| <---- C ----> |
|-A: a-|-B: b-|- c -|
0 4 8 12
pc-^ pb-^
(B*)pc-^因此,当比较这两个指针时,编译器实际上会比较转换后的指针,它们是相等的。
发布于 2013-08-16 20:22:49
我知道答案是有的,但也许这会更直接,并有一个例子来支持。
在此处的if (b == c)中,c操作数上存在从C*到B*的隐式转换
如果你使用下面的代码:
#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;
cout << "The address of (B*)c is 0x" << hex << (B*)c << endl;
if (b == c)
{
cout << "b is equal to c" << endl;
}
else
{
cout << "b is not equal to c" << endl;
}
}你会得到:
The address of b is 0x0x88f900c
The address of c is 0x0x88f9008
The address of (B*)c is 0x0x88f900c
b is equal to c因此,转换为B*类型的c具有与b相同的地址。不出所料。
https://stackoverflow.com/questions/18272909
复制相似问题