c++ - 指向非 union 类的指针的大小可以不同吗?

标签 c++ pointers sizeof language-lawyer

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

指向非 union 类的指针会发生类似的事情吗? C++ 允许虚函数的协变返回类型。假设我们有这样的类:

struct Gadget
{
  // some content
};


struct Widget
{
  virtual Gadget* getGadget();
};

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

所以我的问题是,给定一个特定平台上的特定实用编译器(排除假设的 Hell++),期望所有指向非 union 类类型的指针都相同是否合理尺寸?还是有一个实际的原因可以解释为什么编译器可能希望使用不同的大小同时保持与协变返回类型的兼容?

在存在不同“级别”指针的平台上(例如 __near__far ),假定对两者应用相同属性。

最佳答案

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

6.2.5 Types

27 [...] All pointers to structure types shall have the same representation and alignment requirements as each other. [...]

C++ 实际上需要与 C 实现的二进制兼容性,因为标准对 extern "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 类型。

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

对于尺寸,我想不出它会发生的合理场景,但我不确定这是否可能是我缺乏想象力。

关于c++ - 指向非 union 类的指针的大小可以不同吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25524668/

相关文章:

c++ - 如何使用 C++ 独立 ASIO 库

c - malloc和指针代码演示

相当于宏的 C sizeof

c - 代码运行时输出错误链接列表问题?

c - 两个结构的大小相同,尽管其中一个结构中有一个结构实例

c - 为什么这个缓冲区指向不可寻址的字节?

c++ - cpp静态对象实例化

c++ - 如何防止对正在被销毁的子类实例进行调用函数调用

c++ - 无法访问同一类的私有(private)成员

c - 在 c 中,sizeof()..[-1] 是什么意思