C语言 从手动分配地址的指针访问值



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

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

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

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

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

你可以打印地址(你这样做不可靠,但大概你的编译器没有警告你;我的会警告我不要使用 4 字节整数数量的格式来打印 8 字节地址)。 但是您无法可靠地读取或写入地址中的数据。 可能存在一些计算机(通常是大型机),其中仅读取无效地址(即使不访问其指向的内存)也会产生内存错误。

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

char *c=2000;

整数值赋值(和初始化)到指针是实现定义的行为。

实现定义的行为由 ISO C 标准定义第 3.4.1 节作为:

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

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

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

最新更新