指向标准 C 中整数转换的指针
Pointer to integer conversion in Standard C
我已经在这个网站上阅读了几个关于这个主题的问题,但我仍然有疑问。
在标准 C 中我们可以读到:
6.3.2.3.p.5: An integer can be converted to any pointer type. [...]
6.3.2.3.p.6: Any pointer type can be converted to an integer type. [...].
省略的文字(放在括号 [...] 中)只是讨论了转换失败时可能发生的问题。
但是我的问题更笼统:
- 我观察到 整数数学数字 作为一组值是无限的。
- C 中的任何整数类型只能表示整数数学值的有限子集。
- 在第 6.3.2.3.p5/p6 段中,标准 C11 似乎假定 "every pointer value can be mapped to an integer mathematical value"。
- 此外,C11 标准的编辑方式似乎表明 仅当此数学(或抽象)值无法以开发人员选择的预期整数类型表示时 ,无论出于何种原因,都是操作失败的时候。
我的问题是:我对第 (3.) 点的解释是否正确?
另一方面,当我们定义一个 T 类型的数组,大小为 N,
因为我们可以对数组的位置进行整数运算,
结果很明显,至少在 "local" 级别,在一个数组中,
我们有数组对应的内存块行为
从算术上讲,与从 0 到 N-1 的数字集相同。
通过定义数组或分配对象,我们可以确定,在C中,
内存地址可以 "locally" 视为在算术上等同于整数的子集。
但是,这种 "local" 行为不足以得出结论
标准 C 假定一个内存模型,其内存地址可以被视为 "only one and the same set of integer numbers" 的一部分。
不过,6.3.2.3.p5/p6似乎"suggest"这个说法更有说服力,虽然我不是很确定。
一个额外的问题可以带来更多的启发:
- 在标准C中开启了两个不同的有效指针
p
、q
(即:p != q
)的可能性,当转换为整数类型时,得到的整数值变得 相等 .
My question would be: is my interpretation in point (3.) correct?
该标准指定了类型 uintptr_t
和 intptr_t
,这样每个有效指针都可以转换为 uintptr_t
/ intptr_t
并再次返回。比较 ISO 9899:2011 §7.20.1.4:
7.20.1.4 Integer types capable of holding object pointers
1 The following type designates a signed integer type with the property that any valid pointer to void can be converted to this type, then converted back to pointer to void, and the result will compare equal to the original pointer:
intptr_t
The following type designates an unsigned integer type with the property that any valid pointer to void can be converted to this type, then converted back to pointer to void, and the result will compare equal to the original pointer:
uintptr_t
These types are optional.
尽管这些类型可能不存在,在这种情况下,无法保证每个指针都映射到一个整数。
Is open in standard C the possibility that two different valid pointers p, q, (that is: p != q), when converted to an integer type, the resulting integer values become equal.
是的,这可能会发生。考虑像 8086 这样具有 20 位指针和 16 位 int
的平台。显然,在将指针转换为整数时,许多指针将被映射到同一个整数。如果你采用更大的类型,比如 32 位 long
,那么你会为每个指针获得一个唯一的值。
第 6 段的 [...] 部分给出了您 p != q
问题的答案:
If the result cannot be represented in the integer type, the behavior
is undefined.
因此,如果 p
和 q
是两个不同的有效指针,并且您将这些指针转换为整数 而不调用未定义的行为 ,则结果整数不会比较相等。
您的主要问题的答案在注释 67 中给出(适用于第 5 段):
The mapping functions for converting a pointer to an integer or an
integer to a pointer are intended to be consistent with the addressing
structure of the execution environment.
在我所知道的每个执行环境中,寻址结构都基于自然数的有限子集,其中 0 用作 NULL
指针。因此,如果整数值的范围超出目标硬件中使用的地址范围,则从指针到整数类型的转换一定会成功。
奇怪的是,您将标准的某些部分视为 "just talks about the issues that could happen when conversion fails",而其中一些恰好是解决您问题的部分。
- I observe that the integer mathematical numbers are infinite as a set of values.
是的,但无关紧要。标准说 "any pointer type can be converted to [any] integer type" (强调)。它特指一族 C 数据类型,包括但不限于 int
。您从报价中省略的文字清楚地表明某些整数类型可能无法表示结果。事实上,它说 "The result need not be in the range of values of any integer type"(强调)。
- Any integer type in C can represent only a finite subset of the integer mathematical values.
正确。
- In paragraphs 6.3.2.3.p5/p6 it seems that Standard C11 assumes that "every pointer value can be mapped to an integer mathematical value".
不,事实上不是。您省略的部分文字是“
结果是实现定义的”,用于双向转换,但有某些例外。这种转换的实现定义行为可能是程序退出。我接受标准建议可能存在一个或多个映射,例如你描述了,但不是它假设有一个。
- Besides, the way in that C11 standard is redacted seems to suggest that only when this mathematical (or abstract) value cannot be represented in the intedend integer type choosen by the developer, for any reason, is when the operation fails.
操作永远不会失败。在许多情况下,行为是实现定义的,在某些情况下是未定义的,但这是完全不同的。
但是请注意,该标准对选择提供可选 intptr_t
and/or uintptr_t
类型的实现提出了更多要求,因为这些支持往返、保值void *
到整数类型到 void *
的转换。这样的实现(这是典型的)必须具有从所有可能的指针值到数学整数和可表示整数值的 1-1 映射。
我已经在这个网站上阅读了几个关于这个主题的问题,但我仍然有疑问。
在标准 C 中我们可以读到:
6.3.2.3.p.5: An integer can be converted to any pointer type. [...]
6.3.2.3.p.6: Any pointer type can be converted to an integer type. [...].
省略的文字(放在括号 [...] 中)只是讨论了转换失败时可能发生的问题。
但是我的问题更笼统:
- 我观察到 整数数学数字 作为一组值是无限的。
- C 中的任何整数类型只能表示整数数学值的有限子集。
- 在第 6.3.2.3.p5/p6 段中,标准 C11 似乎假定 "every pointer value can be mapped to an integer mathematical value"。
- 此外,C11 标准的编辑方式似乎表明 仅当此数学(或抽象)值无法以开发人员选择的预期整数类型表示时 ,无论出于何种原因,都是操作失败的时候。
我的问题是:我对第 (3.) 点的解释是否正确?
另一方面,当我们定义一个 T 类型的数组,大小为 N,
因为我们可以对数组的位置进行整数运算,
结果很明显,至少在 "local" 级别,在一个数组中,
我们有数组对应的内存块行为
从算术上讲,与从 0 到 N-1 的数字集相同。
通过定义数组或分配对象,我们可以确定,在C中,
内存地址可以 "locally" 视为在算术上等同于整数的子集。
但是,这种 "local" 行为不足以得出结论
标准 C 假定一个内存模型,其内存地址可以被视为 "only one and the same set of integer numbers" 的一部分。
不过,6.3.2.3.p5/p6似乎"suggest"这个说法更有说服力,虽然我不是很确定。
一个额外的问题可以带来更多的启发:
- 在标准C中开启了两个不同的有效指针
p
、q
(即:p != q
)的可能性,当转换为整数类型时,得到的整数值变得 相等 .
My question would be: is my interpretation in point (3.) correct?
该标准指定了类型 uintptr_t
和 intptr_t
,这样每个有效指针都可以转换为 uintptr_t
/ intptr_t
并再次返回。比较 ISO 9899:2011 §7.20.1.4:
7.20.1.4 Integer types capable of holding object pointers
1 The following type designates a signed integer type with the property that any valid pointer to void can be converted to this type, then converted back to pointer to void, and the result will compare equal to the original pointer:
intptr_t
The following type designates an unsigned integer type with the property that any valid pointer to void can be converted to this type, then converted back to pointer to void, and the result will compare equal to the original pointer:
uintptr_t
These types are optional.
尽管这些类型可能不存在,在这种情况下,无法保证每个指针都映射到一个整数。
Is open in standard C the possibility that two different valid pointers p, q, (that is: p != q), when converted to an integer type, the resulting integer values become equal.
是的,这可能会发生。考虑像 8086 这样具有 20 位指针和 16 位 int
的平台。显然,在将指针转换为整数时,许多指针将被映射到同一个整数。如果你采用更大的类型,比如 32 位 long
,那么你会为每个指针获得一个唯一的值。
第 6 段的 [...] 部分给出了您 p != q
问题的答案:
If the result cannot be represented in the integer type, the behavior is undefined.
因此,如果 p
和 q
是两个不同的有效指针,并且您将这些指针转换为整数 而不调用未定义的行为 ,则结果整数不会比较相等。
您的主要问题的答案在注释 67 中给出(适用于第 5 段):
The mapping functions for converting a pointer to an integer or an integer to a pointer are intended to be consistent with the addressing structure of the execution environment.
在我所知道的每个执行环境中,寻址结构都基于自然数的有限子集,其中 0 用作 NULL
指针。因此,如果整数值的范围超出目标硬件中使用的地址范围,则从指针到整数类型的转换一定会成功。
奇怪的是,您将标准的某些部分视为 "just talks about the issues that could happen when conversion fails",而其中一些恰好是解决您问题的部分。
- I observe that the integer mathematical numbers are infinite as a set of values.
是的,但无关紧要。标准说 "any pointer type can be converted to [any] integer type" (强调)。它特指一族 C 数据类型,包括但不限于 int
。您从报价中省略的文字清楚地表明某些整数类型可能无法表示结果。事实上,它说 "The result need not be in the range of values of any integer type"(强调)。
- Any integer type in C can represent only a finite subset of the integer mathematical values.
正确。
- In paragraphs 6.3.2.3.p5/p6 it seems that Standard C11 assumes that "every pointer value can be mapped to an integer mathematical value".
不,事实上不是。您省略的部分文字是“ 结果是实现定义的”,用于双向转换,但有某些例外。这种转换的实现定义行为可能是程序退出。我接受标准建议可能存在一个或多个映射,例如你描述了,但不是它假设有一个。
- Besides, the way in that C11 standard is redacted seems to suggest that only when this mathematical (or abstract) value cannot be represented in the intedend integer type choosen by the developer, for any reason, is when the operation fails.
操作永远不会失败。在许多情况下,行为是实现定义的,在某些情况下是未定义的,但这是完全不同的。
但是请注意,该标准对选择提供可选 intptr_t
and/or uintptr_t
类型的实现提出了更多要求,因为这些支持往返、保值void *
到整数类型到 void *
的转换。这样的实现(这是典型的)必须具有从所有可能的指针值到数学整数和可表示整数值的 1-1 映射。