我已经为一个特定数据类型的指针分配了一些随机地址。然后我在该特定地址中存储了一个值。当我运行程序时,它会突然终止。
char *c=2000;
*c='A';
printf("%u",c);
printf("%d",*c);
我可以在第一个c
语句中打印printf
的值。但我无法通过第二个获取存储在该地址中的值。我已经在Cygwin GCC编译器和在线ideone.com编译器中执行了。在ideone.com编译器中,它显示运行时错误。这背后的原因是什么?
答案 0 :(得分:2)
当您将地址2000
分配给指针c
时,您假设这将是一个有效的地址。但一般来说,它不是有效的地址。您不能随意选择地址,并期望编译器(和操作系统)已分配该内存供您使用。特别是,第一页内存(通常为4 KiB,通常至少为1 KiB)完全不受限制;所有读取或写入的尝试通常都指示错误而非故意行为,并且MMU(内存管理单元)配置为拒绝访问该内存的尝试。
如果您使用的是嵌入式微处理器,规则可能会有所不同,但在像Cygwin的Windows这样的通用软件中,0x1000(4 KiB)以下的地址通常是禁止的。
你可以打印地址(你做得不可靠,但可能是你的编译器没有警告你;我会警告我使用4字节整数的格式打印8字节地址)。但是您无法在地址处可靠地读取或写入数据。可能有机器(通常是大型机),只需读取无效地址(即使没有访问它指向的内存)也会产生内存故障。
因此,正如Acme在answer中所说,你调用了未定义的行为。您已从编译器负责为指针分配有效地址,但您选择了无效值。崩溃是你做出错误决定的结果。
答案 1 :(得分:1)
char *c=2000;
对指针的整数值的赋值(和初始化)是实现定义的行为。
实现定义的行为由ISO C标准定义 第3.4.1节:
unspeci fi ed行为,其中每个实现都记录了如何选择 是
示例实现定义行为的示例是 当有符号整数移位时,高位的传播 右。
任何依赖于实现定义行为的代码都是 保证在特定平台和/或编译器下工作。手提 程序应该尽量避免这种行为。