为什么我不能将一种类型的变量(比如说double)的地址分配给int类型的指针?

时间:2015-08-05 21:07:02

标签: c++ c pointers

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

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

为什么它不能像解引用一个int指针从double类型的变量读取下一个4个字节并打印它的值?

2 个答案:

答案 0 :(得分:6)

许多计算机都有对齐要求,因此(例如)读取2字节值,它所在的地址必须是2的倍数(同样,必须找到4字节的值)在一个地址是4的倍数,依此类推)。实际上,这种对齐要求很常见,它经常被称为"自然对齐"。

同样,某些类型(例如,浮点类型)对可以作为该类型读取的位序列施加了要求,因此如果您尝试获取某些任意数据并将其视为double,则可能触发类似于浮点异常。

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

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

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

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

答案 1 :(得分:3)

  

如果是指针,我们知道它们的大小始终相同,而不管它指向的数据类型

不,我们知道。

Chapter and verse for C

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

强调补充。

Chapter and verse for C++

3.9.2复合类型
...
3指向void的指针类型或指向对象类型的指针称为对象指针类型。 [注意:一个指针 但是,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。 - end note ]指针类型的值表示 是实现定义的。 布局兼容类型的指针应具有相同的值表示和 对齐要求 (3.11)。 [注意:指向过度对齐类型(3.11)的指针没有特殊表示, 但它们的有效值范围受扩展对齐要求的限制。这个国际 Standard仅指定获取此类指针的两种方法:获取有效对象的地址 过度对齐的类型,并使用运行时指针对齐函数之一。实施可能 提供其他方法来获得过度对齐类型的有效指针值。 - 结束记录]

4指向 cv -qualified(3.9.3)或 cv -unqualified void的指针可用于指向未知类型的对象。 这样的指针应该能够保存任何对象指针。 cv void*类型的对象应具有相同的对象 表示和对齐要求为 cv char*

重点补充。 完全可能对不同的指针类型具有不同的大小和表示。没有理由期望指向int的指针具有与指向double的指针相同的大小和表示,或指向struct类型的指针,或指向函数类型的指针。对于像x86这样的商品平台来说确实如此,但并非全世界都在x86上运行。

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

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

int *ip;
double *dp;

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

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