指向非联合类的指针大小可以不同吗?

Rei*_*ica 7 c++ pointers sizeof language-lawyer

我知道有些硬件平台你需要更多的信息来指向一个char你需要指向int的平台(具有不可寻址字节的平台,所以一个指针char需要存储指向一个字的指针以及一个字节的索引)在这个词).所以sizeof(int*) < sizeof(char*)在这样的平台上有可能.

指向非联合类的指针会发生类似的事情吗?C++允许在虚函数上使用协变返回类型.假设我们有这样的类:

struct Gadget
{
  // some content
};


struct Widget
{
  virtual Gadget* getGadget();
};
Run Code Online (Sandbox Code Playgroud)

任何调用的代码getGadget()在接收时都必须工作Gadget*,但相同的代码(实际上是相同的编译二进制代码)必须在收到指向同样派生类型的指针时工作Gadget(也许是在完全不同的库中定义的代码) .我可以合理地看到这种情况发生的唯一方法是sizeof(T*) == sizeof(U*)所有非联合类类型TU.

所以我的问题是,在一个特定平台上给出一个特定的实用编译器(不包括假设的Hell ++),是否有理由期望所有指向非联合类类型的指针都具有相同的大小?或者是否有一个实际的原因,为什么编译器可能希望使用不同的大小,同时保持符合协变返回类型?

在存在指针的不同"级别"(例如__near__far)的平台上,假设应用于两者的相同属性.

小智 4

C 有一个硬性要求,即指向所有结构类型的所有指针都具有相同的表示和对齐方式。

6.2.5 类型

27 [...]所有指向结构类型的指针应具有相同的表示和对齐要求。[...]

C++ 实际上需要与 C 实现的二进制兼容性,因为标准对 的要求extern "C",因此间接地要求所有指向 C 中有效的结构类型(POD 类型,几乎)的指针在 C++ 中也具有相同的表示和对齐方式。

对于非 POD 类型似乎没有这样的要求,因此在这种情况下将允许实现使用不同的指针大小。你建议这行不通,但要效仿你的例子,

struct G { };
struct H : G { };

struct W
{
  virtual G* f() { ... }
};
struct X : W
{
  virtual H* f() { ... }
};
Run Code Online (Sandbox Code Playgroud)

可以翻译为(伪代码)

struct W
{
  virtual G* f() { ... }
};
struct X : W
{
  override G* f() { ... }
  inline H* __X_f() { return static_cast<H *>(f()); }
};
Run Code Online (Sandbox Code Playgroud)

这仍然符合语言的要求。

指向结构类型的两个指针可能不相同的一个有效原因是,当 C++ 编译器被移植到现有 C 编译器(ABI 设计不佳)的平台时。G是 POD 类型,因此G *需要与 C 中的类型完全相同H。不是 POD 类型,因此H *不需要匹配任何 C 类型。

对于对齐,这实际上可能会发生:真正发生的事情是典型 GNU/Linux 系统上的 x86-32 ABI 要求 64 位整数类型进行 32 位对齐,即使处理器的首选对齐实际上是 64 位。现在出现了另一个实现者,他们决定确实需要 64 位对齐,但如果他们想保持与现有实现的兼容性,就会陷入困境。

对于尺寸,我无法想到会发生这种情况的合理场景,但我不确定这是否是我缺乏想象力。