C 标准规定:
指向 void 的指针应具有与指向字符类型的指针相同的表示和对齐要求。类似地,指向兼容类型的限定或非限定版本的指针应具有相同的表示和对齐要求。所有指向结构类型的指针都应具有相同的表示和对齐要求。所有指向联合类型的指针都应具有相同的表示和对齐要求。指向其他类型的指针不需要具有相同的表示或对齐要求。
即sizeof(int*)
不一定等于sizeof(char*)
- 但sizeof(struct A*)
一定等于sizeof(struct B*)
。
这个要求背后的原理是什么?据我了解,基本类型不同大小背后的基本原理 是支持近/远/巨大指针等用例 (编辑:正如评论和接受的答案中指出的那样,这不是基本原理) - 但不是这个相同的原理适用struct
于内存中不同位置的 s 吗?
答案很简单:struct
andunion
类型可以声明为不透明类型,即:没有对struct
orunion
细节的实际定义。如果指向不同结构的指针具有不同的表示形式,则编译器将无法编译使用此类指针作为参数、返回值、从内存中读取或将它们存储到内存中的代码。
操作不透明指针类型的能力的自然结果是所有此类指针必须具有相同的表示。但是请注意,指向的指针struct
和指向的指针union
可能具有不同的表示形式,以及指向基本类型的指针,例如char
, int
, double
...
关于指针表示的另一个区别是指向数据的指针和指向函数的指针之间的区别,它们可能具有不同的大小。这种差异在当前架构中更为常见,尽管在操作系统和设备驱动程序空间之外仍然很少见。函数指针的 64 位似乎是一种浪费,因为 4GB 应该足够用于代码空间,但现代架构利用这个额外的空间来存储指针签名,以加强代码抵御恶意攻击。另一个用途是利用忽略某些指针位的硬件(例如:x86_64 忽略前 16 位)来存储类型信息或使用未修改的 NaN 值作为指针。
此外,C 标准中的此注释没有正确解决遗留 16 位代码中的近/远/巨大指针属性,因为所有指针都可能是近、远或巨大的。然而,它涵盖了混合模型代码中代码指针和数据指针之间的区别,并且在某些操作系统上似乎仍然存在。
最后,Posix 要求所有指针具有相同的大小和表示形式,因此混合模型代码应该很快成为历史上的好奇心。
有争议的是,对于不同数据类型表示不同的体系结构如今已经很少见了,现在是清理标准并删除此选项的时候了。主要反对意见是支持可寻址单元是大字和 8 位字节使用额外信息寻址的体系结构,这使得char *
和void *
大于常规指针。然而,这样的架构使指针运算变得非常麻烦,而且也非常罕见(我个人从未见过)。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句