我了解在硬件平台上,您需要更多信息来指向char
,而不是指向int
(该平台具有不可寻址的字节,因此,指向char
的指针需要存储指向单词和索引的指针字中的一个字节)。因此,在此类平台上可能存在sizeof(int*) < sizeof(char*)
。
指向非 union 类的指针会发生类似的事情吗? C++允许在虚函数上使用协变返回类型。假设我们有这样的类:
struct Gadget
{
// some content
};
struct Widget
{
virtual Gadget* getGadget();
};
任何调用
getGadget()
的代码都必须在接收到Gadget*
时工作,但是相同的代码(实际上是相同的已编译二进制代码)在接收到指向从Gadget
派生的类型的指针时也必须工作(也许是一个完全定义的代码)不同的库)。我可以合理地看到这种情况的唯一方法是所有非 union 类类型sizeof(T*) == sizeof(U*)
和T
的U
。所以我的问题是,假设在一个特定平台上有一个特定的实用编译器(不包括假设的Hell++),是否可以合理预期所有指向非 union 类类型的指针的大小相同?还是有一个实际的原因,为什么编译器可能希望在保持与协变返回类型兼容的情况下使用不同的大小?
在存在不同“级别”的指针的平台上(例如
__near
和__far
),假定对两个对象都应用相同的属性。 最佳答案
C严格要求所有指向所有结构类型的指针都必须具有相同的表示形式和对齐方式。
由于标准对extern "C"
的要求,因此C++有效地要求与C实现二进制兼容,因此间接地,这要求所有指向在C中有效的结构类型的指针(几乎是POD类型)也必须在C++中具有相同的表示形式和对齐方式。
对于非POD类型似乎没有这样的要求,因此在这种情况下,允许实现使用不同的指针大小。您建议这行不通,但请按照您的示例,
struct G { };
struct H : G { };
struct W
{
virtual G* f() { ... }
};
struct X : W
{
virtual H* f() { ... }
};
可以翻译成(伪代码)struct W
{
virtual G* f() { ... }
};
struct X : W
{
override G* f() { ... }
inline H* __X_f() { return static_cast<H *>(f()); }
};
仍然符合该语言的要求。两个指向结构类型的指针可能不相同的有效原因是,将C++编译器移植到具有现有C编译器且ABI设计不良的平台上。
G
是POD类型,因此G *
必须与C中的类型完全相同。H
不是POD类型,因此H *
不需要与任何C类型匹配。对于对齐,这实际上可能会发生:真正发生的事情是,即使处理器的首选对齐方式实际上是64位,但典型的GNU/Linux系统上的x86-32 ABI要求64位整数类型必须是32位对齐的。 。现在出现了另一个实现者,他们决定确实需要64位对齐,但是如果他们想与现有实现保持兼容,就会陷入困境。
对于尺寸,我无法想到会发生这种情况的合理情况,但是我不确定这是否可能是我缺乏想象力的原因。