对于所有数据类型,所有数据指针在一个平台上的大小是不是相同? [复制]
Posted
技术标签:
【中文标题】对于所有数据类型,所有数据指针在一个平台上的大小是不是相同? [复制]【英文标题】:Are all data pointers the same size in one platform for all data types? [duplicate]对于所有数据类型,所有数据指针在一个平台上的大小是否相同? [复制] 【发布时间】:2010-11-17 11:49:13 【问题描述】:char*
、int*
、long*
甚至 long long*
的大小是否相同(在给定平台上)?
【问题讨论】:
我的好奇心引出了一个问题:你为什么在乎? :-) char c[100];诠释*我;我 = &c[0];我 = 0x5555u;问题:c[0] == 0x55u? c[1] == 0x55u? 将 char 的地址分配给指向 int 的指针并不是一个好主意...... @c-stranger:当然不能保证。如果机器是大端的,那么 c 的前两个字节将为 0。此外,不能保证 c 的对齐方式与 int 的对齐方式一样严格——尽管它可能是。 如果您正在编写可移植的 c,这是一个重要的问题,有一个带有指针的结构,并且您希望内存对齐。 brewx.qualcomm.com/bws/content/gi/common/appseng/en/… 【参考方案1】:不保证它们的大小相同,尽管在我有经验的平台上它们通常是相同的。
C 2011 online draft:
6.2.5 类型 ... 28 指向void
的指针应具有与 指向字符类型的指针。48) 同样,指向合格或不合格版本的指针 兼容类型应具有相同的表示和对齐要求。全部 指向结构类型的指针应具有相同的表示和对齐要求 作为彼此。所有指向联合类型的指针都应具有相同的表示形式和 对齐要求彼此。指向其他类型的指针不必相同 表示或对齐要求。
48) 相同的表示和对齐要求意味着可互换性 函数的参数、函数的返回值以及联合的成员。
【讨论】:
+1 参考标准,真正确定并涵盖所有边缘情况。【参考方案2】:不一定。该标准不保证sizeof(double*) == sizeof(int*)
。例如,假设一个处理器具有两条不同宽度的地址总线(例如在某些哈佛架构处理器上),它可能具有不同大小的指针。
【讨论】:
哇,真的吗?我没有意识到这一点。 但是,请注意 void * 必须能够保存任何数据指针。void*
不能直接取消引用 - 您必须将其转换回原始类型。据推测,即使指针的表示实际上在类型之间有所不同,当你转换回原始表示时也会恢复。
查尔斯,你误解了所谈论的内容。它与int
和double
的大小无关(它可以是任何其他两种类型)。关键是 指针 本身的大小可以不同。
@CharlesBretana:一点也不傻。 sizeof
(可能应用于可变长度数组类型时除外)的开销正好为零;它解析为一个常数。 sizeof (some_type*)
比 8
更好,因为它更明确 -- 并且 这意味着代码可以移植到其他系统。【参考方案3】:
在具有存储(分页)RAM 和/或闪存的 16 位嵌入式处理器上,使用页面可能会导致指针大小不同 - 尽管这与它们指向的数据大小无关。
例如,在具有存储闪存的飞思卡尔 HCS12 处理器上,数据指针都是 16 位。
但是,函数指针对于近指针(用于与调用函数在同一页中的代码,或在未存储的闪存中)为 16 位,对于远指针(对于不同页中的代码)为 24 位,包含页码在地址中。
如果要将常量数据存储在分页闪存中,事情会很复杂,因为由于数据指针大小的限制,使用数据的函数必须与正在访问的数据在同一页中。
可以想象,带有存储 RAM 的 16 位处理器同样具有不同大小的近端和远端数据指针。
【讨论】:
对象指针部分不正确,因为 HCS12 是冯诺依曼,您可以将对象和函数存储在闪存中的任何位置,可以选择使用存储闪存。然后数据指针是 16 位或 24 位,这取决于是否使用far
声明。函数指针更高级一点,因为不仅指针的大小不同于 16 和 24,而且您还必须在汇编程序级别使用正确的指令:JSR
与 CALL
和 RTS
与 RTC
。 【参考方案4】:
请注意 C 标准所说的内容 - 正如 John Bode 所引用的那样。还要注意,C 标准根本没有说明函数指针的大小。
POSIX 标准规定了一些额外的要求:
2.12.3 指针类型
所有函数指针类型都应与指向 void 的类型指针具有相同的表示。将函数指针转换为 void * 不应改变表示。这种转换产生的 void * 值可以使用显式强制转换转换回原始函数指针类型,而不会丢失信息。
注意:ISO C 标准不要求这样做,但符合 POSIX 要求。
【讨论】:
请注意,此部分已从 POSIX 2008 的 POSIX 2013 修订版中删除。对于大多数实际用途,它仍然存在,但它现在是dlsym()
行为的结果,而不是更多一般性发言。有时(也许这十年),我需要写下变化。【参考方案5】:
在 C 或 C++ ISO 标准中都没有这样的保证,但在实践中,我还没有看到一个平台不能保证这一点。
请注意,不管怎样,reinterpret_cast
'将一个指针指向另一个指针通常会导致 U.B.,但有一些例外(void*
和 unsigned char*
用于 POD)。任何工会的伎俩也是如此。所以显而易见的问题是:你为什么要关心?
【讨论】:
【参考方案6】:使用 Watcom C 编程 x86 实模式时,您可以使用 16 位近指针和 32 位远指针的混合内存模型。
【讨论】:
【参考方案7】:在受保护模式的 DOS 时代,函数指针和数据指针的长度可能不同,因为数据可能位于不同的部分。
【讨论】:
【参考方案8】:通常是的,所有指向任何东西的指针,无论它们指向 int 或 long 或 string 或字符串数组或函数,都指向单个内存地址,该地址在机器上是相同大小的。这是因为机器上的处理器有一个地址寄存器,这些指针被加载到其中,并且该地址寄存器的大小控制指针的大小。
唯一的例外可能是像旧的 Intel 8088 16 位机器这样的情况,其中有一个两步过程来确定内存地址,涉及 16 位段指针,(它在 1MByte 地址内标识了一个 64K 的内存块空间),然后是第二个 16 位内存地址,用于标识该段内的特定内存地址。然后将这两个 16 位地址组合起来,得到完整的 20 位内存地址。那么,在那种情况下,我想有可能区分单独的 16 位地址和组合的 20 位地址。
【讨论】:
C/C++ 实现不需要在指针的存储位置实际存储原始内存地址。例如,它可以是一个句柄(例如,实现指针边界检查)。 @Pavel,我承认我不是 C++ 人,而且我只了解句柄,但作为句柄是一种指针,我敢说它必须是与机器上所有其他指针的大小相同。 句柄不是一种指针。句柄是一个不透明的标识符。它绝对可以是任何东西——例如,到其他地方的某个数组的索引。 成员函数指针尤其如此。我最近学习了这个主题:不能保证指针实际上是地址。它只是我们使用的大多数系统的最佳表示。 考虑一个字寻址 CPU,其中机器地址指定一个 32 位字的地址。指向较小类型的指针,例如char*
(假设CHAR_BIT == 8
)可能需要同时保存字指针和字内的字节偏移量。我曾在 Cray 矢量系统上工作过,它做了类似的事情,除了字节偏移量存储在 64 位字的其他未使用的高位 3 位中。以上是关于对于所有数据类型,所有数据指针在一个平台上的大小是不是相同? [复制]的主要内容,如果未能解决你的问题,请参考以下文章