指向非并集类的指针的大小不同
Can size of pointers to non-union classes differ?
我知道有些硬件平台需要比指向int
更多的信息来指向char
(该平台具有不可寻址的字节,因此指向char
的指针需要存储指向单词的指针以及单词中字节的索引)。因此CCD_ 4在这样的平台上是可能的。
指向非并集类的指针会发生类似的情况吗?C++允许在虚拟函数上使用协变返回类型。假设我们有这样的类:
struct Gadget
{
// some content
};
struct Widget
{
virtual Gadget* getGadget();
};
任何调用getGadget()
的代码在接收Gadget*
时都必须工作,但当接收到指向从Gadget
派生的类型的指针(可能是在完全不同的库中定义的类型)时,相同的代码(实际上是相同的编译的二进制代码)也必须工作。我能合理地看到这种情况发生的唯一方法是针对所有非并集类类型T
和U
的sizeof(T*) == sizeof(U*)
。
因此,我的问题是,给定一个特定平台上的一个特定的实用编译器(不包括假设的Hell++),期望所有指向非并集类类型的指针都具有相同的大小是否合理?或者,编译器可能希望使用不同的大小,同时保持与协变返回类型的一致性,这是否有实用的原因?
在存在不同"级别"指针的平台上(如__near
和__far
),假设相同的属性应用于两者。
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() { ... }
};
可以转换为(伪代码)
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和C++假设内存是线性字节可寻址的。然而,某些平台(早期的ARM)坚持使用单词对齐加载和存储。在这种情况下,编译器的责任是将指针舍入到单词边界,然后在获取字符时执行必要的移位操作。
但由于这一切都只在加载和存储时完成,所以所有指针看起来仍然相同。
- 1d 智能指针不适用于语法 (*)++
- 在C#中处理C++指针而不使用unsafe的最佳方法
- 为什么使用 "this" 指针调用派生成员函数?
- 函数向量_指针有不同的原型,我可以构建一个吗
- 使用指针从C++中的数组中获取最大值
- 助记符和指向成员语法的指针
- 嵌入方指针压缩已禁用
- 数组的指针从不分段故障
- C++ 指针的内存地址和指向数组的内存地址如何相同?
- 何时在引用或唯一指针上使用移动语义
- QMetaObject invokeMethod的基于函数指针的语法
- 如何从 std::atomic 中提取指针 T<T>?
- 如何在 C# 中映射双 C 结构指针?
- C++将浮点指针值舍入为小数位数
- 为什么++(*p)更改指针值
- 调整大小后指向元素值的指针unordered_map有效?
- 正在将指针转换为范围
- 使用指向成员的指针将成员函数作为参数传递
- 将OpenCV C++重写为EmguCV C#-如何使用指针
- C++-试图将函数指针推回到另一个CPP文件中的矢量时出错