0

我已经为特定数据类型的指针分配了一些随机地址。然后我在该特定地址中存储了一个值。当我运行程序时,它突然终止。

char *c=2000;
*c='A';
printf("%u",c);
printf("%d",*c);

我可以打印c第一个printf语句中的值。但是我无法通过第二个地址获取存储在该地址中的值。我已经在 Cygwin GCC 编译器和在线 ideone.com 编译器中执行过。在 ideone.com 编译器中,它显示运行时错误。这背后的原因是什么?

4

2 回答 2

2

当您将地址分配给2000指针c时,您假设这将是一个有效地址。但是,一般来说,它不是一个有效的地址。您不能随机选择地址并期望编译器(和操作系统)已分配该内存供您使用。特别是内存的第一页(通常为 4 KiB,通常至少为 1 KiB)是完全不受限制的;所有读取或写入那里的尝试通常都表明错误而不是故意行为,并且 MMU(内存管理单元)被配置为拒绝访问该内存的尝试。

如果您使用的是嵌入式微处理器,则规则可能会有所不同,但在带有 Cygwin 的 Windows 等通用操作系统上,0x1000 (4 KiB) 以下的地址通常是禁止的。

您可以打印地址(您这样做不可靠,但大概您的编译器没有警告您;我会警告我使用 4 字节整数格式来打印 8 字节地址)。但是您不能可靠地读取或写入地址处的数据。可能有机器(通常是大型机)仅仅读取无效地址(即使没有访问它指向的内存)会产生内存故障。

因此,正如Acme在他们的回答中所说,您调用了未定义的行为。您已从编译器那里承担了为指针分配有效地址的责任,但您选择了无效值。崩溃是您错误决定的结果。

于 2013-11-08T07:03:35.743 回答
1

char *c=2000;

将整数值分配(和初始化)给指针是实现定义的行为。

ISO C 标准在第 3.4.1 节中将实现定义的行为定义为:

未指定的行为,其中每个实现都记录了如何做出选择

示例 实现定义行为的一个示例是当有符号整数右移时高位的传播。

任何依赖于实现定义行为的代码只能保证在特定平台和/或编译器下工作。便携式程序应尽量避免此类行为。

于 2013-11-08T06:53:48.177 回答