为什么我不能将一个类型(比如双精度)的变量的地址分配给 int 类型的指针?



在指针的情况下,我们知道它们的大小总是相同的,无论它所指向的变量的数据类型如何。

取消引用指针时需要数据类型,以便它知道应该读取多少数据。那么为什么我不能将双精度类型的变量地址分配给 int 类型的指针呢?

为什么不能像取消引用 int 指针从双精度类型的变量中读取接下来的 4 个字节并打印其值那样发生?

许多计算机都有对齐要求,因此(例如(要读取 2 字节值,它所在的地址必须是 2 的倍数(同样,4 字节值必须位于 4 的倍数的地址,依此类推(。事实上,这种对齐要求非常普遍,因此经常被称为"自然对齐"。

同样,某些类型(例如,浮点

类型(对可读取为该类型的位序列施加了要求,因此,如果您尝试获取一些任意数据并将其视为双精度值,则可能会触发浮点异常之类的内容。

如果你想做得足够糟糕,你可以使用强制转换将指针转换为目标类型(但结果(如果有的话(通常不是可移植的(。

可以保证可以将指向任何其他类型的对象的指针转换为指向无符号字符的指针,并使用它来读取表示 pointee 对象的字节。

此外,如果您主要想要一个不透明的指针,而不附加类型信息,则可以将指向某个其他类型的指针分配给void *

最后:不,并非所有指针实际上都相同。指向不同类型的指针可以是不同的大小(例如,在早期的 Cray 编译器上,char *int *有很大不同(。

对于指针,我们知道它们的大小总是相同的,无论它所指向的变量的数据类型如何。

不,我们不知道

C的章节和诗句

6.2.5 类型
...
28 指向void的指针应具有与指向字符类型的指针。48( 同样,指向限定或非限定版本的指针兼容类型应具有相同的表示和对齐要求。都指向结构类型的指针应具有相同的表示和对齐要求彼此之间。指向联合类型的所有指针应具有相同的表示形式,并且相互对齐的要求。指向其他类型的指针不必相同表示或对齐要求。
48( 相同的表示和对齐要求意味着可互换性函数的参数、函数的返回值和联合成员。

强调添加。

C++的章节和诗句

3.9.2 化合物类型
...
3 指向void的指针或指向对象类型的指针的类型称为对象指针类型。[ 注意:指针但是,To void 没有指向对象的指针类型,因为void不是对象类型。— 尾注 ]可以指定函数的指针类型称为函数指针类型。指向对象的指针类型T称为"指向T的指针"。[示例:指向类型 int 的对象的指针称为"指向int的指针"和指向类 X 对象的指针称为"指向X的指针"。— 结束示例 ]除了对于指向静态成员的指针,引用"指针"的文本不适用于指向成员的指针。指针允许使用不完整的类型,尽管对可以使用它们执行的操作有限制 (3.11(。对象指针类型的有效值表示内存中字节的地址 (1.7( 或 null指针 (4.10(。如果一个 T 类型的对象位于地址 A ,则 cv 类型的指针T*其值为地址A被称为指向该对象,而不管该值是如何获得的。[ 注意:例如,超过数组 (5.7( 末尾的地址将被视为指向可能位于该地址的数组元素类型。对指向的指针有进一步的限制具有动态存储持续时间的对象;参见 3.7.4.3.— 尾注 ]指针类型的值表示形式是实现定义的。指向布局兼容类型的指针应具有相同的值表示形式,并且对齐要求 (3.11(。[ 注意:指向过度对齐类型的指针 (3.11( 没有特殊的表示形式,但它们的有效值范围受到扩展对齐要求的限制。这个国际标准仅指定了获取此类指针的两种方法:获取有效对象的地址过度对齐的类型,并使用运行时指针对齐函数之一。实现可以提供获取过度对齐类型的有效指针值的其他方法。— 尾注 ]

4 指向符合 cv 标准的 (3.9.3( 或不符合 cv 标准的void的指针可用于指向未知类型的对象。这样的指针应该能够容纳任何对象指针。cv void* 类型的对象应具有相同的作为简历char*的表示和对齐要求。

强调添加。 对于不同的指针类型,完全可以有不同的大小和表示形式。 没有理由期望指向int的指针与指向double的指针、指向struct类型的指针或指向函数类型的指针具有相同的大小和表示形式。 对于像x86这样的商品平台来说,这是正确的,但并不是世界上所有的平台都在x86上运行。

这就是为什么在没有显式强制转换的情况下,不能将一种类型的指针值分配给另一种类型的指针值的原因(在 C 中在 void * 和其他指针类型之间进行转换除外(,因为可能需要更改表示形式。

其次,指针算术取决于指向类型的大小。 假设您有指向 32 位int和 64 位double的指针:

int *ip;
double *dp;

表达式 ip + 1 将返回下一个整数对象的地址(当前地址加 4(,而表达式 dp + 1 将返回下一个双精度对象的地址(当前地址加 8(。

如果我将double的地址分配给指向int的指针,则递增该int指针不会将我带到下一个double对象。

最新更新