我有下面的程序,其中内存是只读的,但我仍然可以写入它。
main()
{
char *p="amit";
p[0]="s";
printf("%s",p);
}
输出是“smit”
p
由于指向只读位置,它是预期的输出吗?当我在 GCC 或 Visual C++ 上运行这个程序时,我得到了一个分段错误,但在 Turbo C++ 上我得到了“smit”。
请确认此行为...
未定义的行为是未定义的行为:无论你得到什么,你都不能抱怨。
字符串字面量曾经位于可写内存中。较旧的编译器具有此行为。一些编译器(至少是旧版本的 gcc,它似乎在 4.X 版本中已被删除)可以选择获取它。我建议不要使用它,除非帮助移植旧应用程序。
写入字符串文字会产生未定义的行为,因此当您这样做时,允许编译器做任何它想做的事情。
简单的答案是 Turbo C++ 编译为实模式,因此没有任何内存受到保护。编译器和操作系统都不会阻止您在任何地方编写任何内容。
字符串使用的内存"amit"
不必是只读的。实际上,这是依赖于编译器的,因此您会看到这种现象。
问题是您在堆栈上声明了一个指针,但不清楚“amit”应该存储在哪里。您也需要堆栈上的字符串,最简单的方法是通过将 p 从指针更改为字符数组来为其分配存储空间。
将您的代码更改为:
main()
{
char p[] = "amit";
p[0]='s';
printf("%s",p);
}
运行时机器中的内存是只读的,这完全无关紧要。在尝试通过 p 间接写入内存(我假设是读/写)之前,您必须首先定义该内存。当然,如果运行时内存确实是只读的,那么无论您修复多少编译错误,它都不会工作。
所以你可能有:
main()
{
char amit[20] = "amit";
char *p = amit; // which is the same as &amit[0]
// yes, you are permitted to write into amit[] like these next two lines:
p[0]="s";
p[1] = '\0'; // you must terminate the string if you don't want to use strcpy( ) or its friends
// but it's better in every way to strcpy( ) into amit[], like this:
strcpy( amit, "s" );
printf("%s",p);
}
用于“amit”的内存不仅是可读的,而且这是依赖于编译器的天气,我们可以在位置 p[0] 上重写或不重写。我在 (GCC) 4.1.2 中也观察到了同样的情况。是的,它的预期输出和它的未定义的行为...