c - 为什么所有指向结构的指针都必须具有相同的大小?

标签 c pointers language-lawyer

C 标准规定:

A pointer to void shall have the same representation and alignment requirements as a pointer to a character type. Similarly, pointers to qualified or unqualified versions of compatible types shall have the same representation and alignment requirements. All pointers to structure types shall have the same representation and alignment requirements as each other. All pointers to union types shall have the same representation and alignment requirements as each other. Pointers to other types need not have the same representation or alignment requirements.


sizeof(int*) 不一定等于 sizeof(char*) - 但 sizeof(struct A*) 一定等于 sizeof(struct B*)
这个要求背后的原理是什么?据我了解,rationale behind differing sizes for basic types 是支持近/远/巨大指针等用例( 编辑 :正如评论和接受的答案中指出的那样,这不是基本原理) - 但同样的基本原理不适用到 struct s 在内存中的不同位置?

最佳答案

答案很简单:structunion类型可以声明为不透明类型,即:没有 struct 的实际定义或 union细节。如果指针的表示根据结构的详细信息而不同,编译器将如何确定用于作为参数、返回值或什至只是从内存中读取或存储到内存中的不透明指针的表示。
操作不透明指针类型的能力的自然结果是所有此类指针必须具有相同的表示。但是请注意指向 struct 的指针和指向 union 的指针可能有不同的表示,以及指向基本类型的指针,例如 char , int , double ...
关于指针表示的另一个区别是指向数据的指针和指向函数的指针之间的区别,它们可能具有不同的大小。这种差异在当前架构中更为常见,尽管在操作系统和设备驱动程序空间之外仍然很少见。函数指针的 64 位似乎是一种浪费,因为 4GB 应该足够用于代码空间,但现代架构利用这个额外的空间来存储指针签名,以加强代码抵御恶意攻击。另一个用途是利用忽略某些指针位的硬件(例如:x86_64 忽略前 16 位)来存储类型信息或使用未修改的 NaN 值作为指针。
此外,C 标准中的此注释没有正确解决遗留 16 位代码中的近/远/巨大指针属性,因为所有指针都可能是近、远或巨大的。然而,它涵盖了混合模型代码中代码指针和数据指针之间的区别,并且在某些操作系统上似乎仍然存在。
最后,Posix 要求所有指针具有相同的大小和表示形式,因此混合模型代码应该很快成为历史上的好奇心。
有争议的是,对于不同数据类型表示不同的体系结构如今已经很少见了,现在是清理标准并删除此选项的时候了。主要反对意见是支持可寻址单元是大字和 8 位字节使用额外信息寻址的体系结构,使得 char *void *比普通指针大。然而,这样的架构使指针运算变得非常麻烦,而且也非常罕见(我个人从未见过)。

关于c - 为什么所有指向结构的指针都必须具有相同的大小?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68718097/

相关文章:

c# - 无法在开关 block 中使用只读字段的原因是什么?

c - C11 中类型名称作用域的概念

C++ - 不明确的重载模板解析/推导

c - 关闭文件描述符之前的 printf 命令仍在外部文件中调用

c - 逗号运算符的评估顺序和 C 中的赋值是可预测的吗?

c - 函数返回指针与 C 中的函数返回数组

c - 将数组传递给函数会更改其值吗?

c - 如何使用基于TCP的HTTP下载图片?

c - 如何覆盖 C 库中的 fprintf?如何将 GCC 选项添加到顶级 CMakeLists.txt?

c - C 中的指针,使用数组获得意外结果