我在这个网站上已经阅读了几个关于这个主题的问题,但我仍然有疑问。
在标准C中,我们可以阅读:
6.3.2.3.p.5:整数可以转换为任何指针类型。 [...]
6.3.2.3.p.6:任何指针类型都可以转换为整数类型。 [...]。
省略的文本(将放在括号[...]中)只讨论转换失败时可能发生的问题。
但是我的问题更为笼统:
我的问题是:是我的解释(3。)正确吗?
另一方面,当我们定义一个大小为 N 的 T 类型的数组时,
因为我们可以对数组的位置进行整数运算,
结果很明显,至少在“本地”级别,在数组中,
我们有相应的数组内存行为
同样地,算术上,也就是说,从 0 到 N-1 的数字集合。
通过定义数组或分配的对象,我们可以确定,在C中, 存储器地址可以被“局部地”视为算术上等于整数的子集。
然而,这种“本地”行为不足以得出结论 标准C假设一个内存模型,其内存地址可以被视为“只有一个同一组整数”的一部分。
然而,6.3.2.3.p5 / p6似乎“暗示”这个更强有力的断言,尽管我并不完全确定。
另一个问题可能会带来更多亮点:
p
,q
(即:p != q
)的可能性,当转换为整数类型时,结果整数值变为的等于即可。答案 0 :(得分:5)
奇怪的是,你忽略了部分标准,“只是谈论转换失败时可能发生的问题”,其中一些正是解决你问题的部分。
- 我观察到整数数学数字是无穷大的一组值。
醇>
是的,但无关紧要。标准说“任何指针类型都可以转换为[任意]整数类型”(强调添加)。它特指一系列C数据类型,包括但不限于int
。您在引用中省略的文本清楚地表明某些整数类型可能无法表示结果。实际上,它说“结果不必在任何整数类型”的值范围内(强调添加)。
- C中的任何整数类型只能表示整数数学值的有限子集。
醇>
真。
- 在第6.3.2.3.p5 / p6段中,似乎标准C11假定“每个指针值都可以映射到整数数学值”。
醇>
不,事实上不是。你省略的部分文字是“ 结果是实现定义的“用于双向转换,但有一些例外。这种转换的实现定义行为可能是程序退出。我接受标准表明可能存在映射或映射,例如你描述,但不是假设有一个。
- 此外,编辑C11标准的方式似乎表明,只有当这个数学(或抽象)值无法在开发人员选择的整数类型中表示时,无论出于何种原因,都是在操作失败时。 / LI> 醇>
操作永远不会失败。在许多情况下,行为是实现定义的,在某些情况下它是未定义的,但这完全不同。
但请注意,该标准对选择提供可选intptr_t
和/或uintptr_t
类型的实现提出了更多要求,因为这些要求支持往返,保值{{1} }到整数类型到void *
次转换。此类实现(通常)必须具有从所有可能指针值的1-1映射,不仅是数学整数,还有可表示的整数值。
答案 1 :(得分:2)
我的问题是:我在第(3)点的解释是否正确?
标准指定类型uintptr_t
和intptr_t
,以便每个有效指针可以转换为uintptr_t
/ intptr_t
并再次返回。比较ISO 9899:2011§7.20.1.4:
7.20.1.4能够保存对象指针的整数类型
1以下类型指定一个带符号的整数类型,其属性是任何有效的void指针都可以转换为此类型,然后转换回指向void的指针,结果将等于原始指针:
intptr_t
以下类型指定一个无符号整数类型,其属性是任何有效的void指针都可以转换为此类型,然后转换回指向void的指针,结果将与原始指针进行比较:
uintptr_t
这些类型是可选的。
但这些类型可能不存在,在这种情况下,不保证每个指针都映射到一个整数。
在标准C中打开两个不同有效指针p,q的可能性(即:p!= q),当转换为整数类型时,得到的整数值变得相等。
是的,这可能发生。考虑像8086那样具有20位指针和16位int
的平台。显然,在将指针转换为整数时,许多指针将被映射到同一个整数。如果你采用更大的类型,比如32位long
,那么你会得到每个指针的唯一值。
答案 2 :(得分:1)
第{6}条[...]部分给出了p != q
问题的答案:
如果结果无法以整数类型表示,则表现为行为 未定义。
因此,如果p
和q
是两个不同的有效指针,并且您将这些指针转换为整数而不调用未定义的行为,则生成的整数将不会比较相等
主要问题的答案见附注67(适用于第5段):
用于将指针转换为整数或。的映射函数 整数到指针的目的是与寻址一致 执行环境的结构。
在我所知道的每个执行环境中,寻址结构基于自然数的有限子集,其中0用作NULL
指针。因此,如果整数值范围超出目标硬件中使用的地址范围,则保证从指针转换为整数类型。