【发布时间】:2016-06-02 22:21:01
【问题描述】:
在 C 中,引用 空指针 是未定义行为,但是空指针值具有位表示,在某些体系结构中使其指向有效地址(例如地址 0)。
为了清楚起见,我们称这个地址为空指针地址。
假设我想在一个不受限制地访问内存的环境中用 C 语言编写一个软件。进一步假设我想在空指针地址写入一些数据:我将如何以符合标准的方式实现?
示例案例(IA32e):
#include <stdint.h>
int main()
{
uintptr_t zero = 0;
char* p = (char*)zero;
return *p;
}
当使用 gcc 和 -O3 为 IA32e 编译时,此代码将转换为
movzx eax, BYTE PTR [0]
ud2
由于UB(0是空指针的位表示)。
既然C接近低级编程,相信一定有办法访问空指针地址,避免UB。
只是为了清楚
我问的是标准对此有何规定,不是如何以实现定义的方式实现这一点。
我知道后者的答案。
【问题讨论】:
-
空指针和地址0x0不一样。
-
我认为您应该使用针对预期环境的编译器进行尝试。
-
没有符合标准的方法来做到这一点,因为标准没有提供访问任意内存的方法。您将不得不做一些与实现相关的事情。检查你的编译器文档,看看你的实现允许什么。
-
“我问的是标准对此有何规定,而不是如何以实现定义的方式实现这一点。” - 这导致根本没有答案。因为分配给整数类型
zero的0到指针的转换已经是未定义的行为。该标准仅允许将指针转换为该类型并返回。即使使用不同的指针类型也已经是 UB。 -
@2501:嗯,这取决于。在简单的标准兼容上下文中,指针的值是毫无意义的。基本上,一个指针可以是一个空指针,或者指向一个“数组”(其中包括单个对象,这些对象是长度为1的数组)。无论哪种方式,实际的位表示都是特定于实现的。只有 null 指针 或者它们指向同一个“数组” - 或者正好超过最后一个元素时才允许比较两个指针。但是对于例如嵌入式系统您必须“改变规则”并依赖特定的,即实现定义的行为。
标签: c language-lawyer undefined-behavior null-pointer