"C++ compilers use a binary object layout"这句话的含义和用途是什么

What is the meaning and use of the sentence "C++ compilers use a binary object layout"

在查看此 C++ 常见问题解答时 https://isocpp.org/wiki/faq/mixing-c-and-cpp#cpp-objs-passed-to-c 我遇到了语句

Most C++ compilers use a binary object layout that causes this conversion to happen with multiple inheritance and/or virtual inheritance.

我无法理解它的含义和应用。根据 C++ 常见问题解答,此对象布局机制有助于 C++ 编译器进行下面提到的检查

In C++ it is easy to check if a Derived* called dp points to the same object as is pointed to by a Base* called bp: just say if (dp == bp) .... The C++ compiler automatically converts both pointers to the same type, in this case to Base*, then compares them. Depending on the C++ compiler’s implementation details, this conversion sometimes changes the bits of a pointer’s value.

任何人都可以帮助理解任何流行的 C++ 编译器的 二进制对象布局 以及可能的变化以及 位的变化的相应机制指针的值。 以及它如何帮助比较 Base/Derived 类.

的指针

编辑:请解释为什么下面的陈述也是有效的。

NOTE: you must be especially careful when converting both to void* since that conversion will not allow either the C or C++ compiler to do the proper pointer adjustments! The comparison (x == y) might be false even if (b == d) is true:

在此上下文中,"binary object layout" 表示 "how the binary data comprising the object is layed out in memory."

考虑这个 C++ 代码:

struct Left
{
  int ll;
};

struct Right
{
  int rr;
};

struct Derived : Left, Right
{
  int dd;
};

在内存中组织这些(概念上)的一种可能方法如下:

+ Derived ----------------+
| + Left +  + Right +     |
| | ll   |  | rr    |  dd |
| +------+  +-------+     |
+-------------------------+

当然,class只是3int秒,所以有了上面的概念布局,真正的布局就是这样:

+ Derived------+
| ll | rr | dd |
+--------------+

现在想象一下这段代码:

Derived d;
Dervied *pd = &d;
Left *pl = &d;
Right *pr = &d;

pd 指向 d 的开始,这与其 ll 成员的开始相同。

pl 将指向 dLeft 子对象。 Left 的开头是 ll 成员的开头。比较pl == pd时,需要将pd转换为Left*类型。请记住 pd 已经指向 ll 的开始,因此不需要更改 pd 的值。纯粹是概念上的转换(类型的改变)。

pr 指向 dRight 子对象。由于 Right 对象以 rr 成员开头,因此 pr 指向 rr。同样,执行 pr == pd 需要将 pd 转换为类型 Right*dRight 子对象以 rr 成员开始,但 pd 指向 ll 成员的地址。因此,pd 的值(= 位)必须通过此转换(增加一个 int 的大小) 更改 以指向 rr 反而。实际上,在将 &dDerived* 转换为 Right* 以便用它初始化 pr 时,这种转换已经发生过一次。

这也可以解释为什么 void* 类型的比较不起作用。显然,&d.ll != &d.rr,即使 pl == pr.