0

我有下面的程序,其中内存是只读的,但我仍然可以写入它。

main()
{
char *p="amit";
p[0]="s";
printf("%s",p);
}

输出是“smit”

p由于指向只读位置,它是预期的输出吗?当我在 GCC 或 Visual C++ 上运行这个程序时,我得到了一个分段错误,但在 Turbo C++ 上我得到了“smit”。

请确认此行为...

4

6 回答 6

3

未定义的行为是未定义的行为:无论你得到什么,你都不能抱怨。

字符串字面量曾经位于可写内存中。较旧的编译器具有此行为。一些编译器(至少是旧版本的 gcc,它似乎在 4.X 版本中已被删除)可以选择获取它。我建议不要使用它,除非帮助移植旧应用程序。

于 2011-02-28T06:32:43.723 回答
3

写入字符串文字会产生未定义的行为,因此当您这样做时,允许编译器做任何它想做的事情。

简单的答案是 Turbo C++ 编译为实模式,因此没有任何内存受到保护。编译器和操作系统都不会阻止您在任何地方编写任何内容。

于 2011-02-28T06:33:11.257 回答
1

字符串使用的内存"amit"不必只读的。实际上,这是依赖于编译器的,因此您会看到这种现象。

于 2011-02-28T06:32:29.700 回答
1

问题是您在堆栈上声明了一个指针,但不清楚“amit”应该存储在哪里。您也需要堆栈上的字符串,最简单的方法是通过将 p 从指针更改为字符数组来为其分配存储空间。

将您的代码更改为:

main()
{
  char p[] = "amit";
  p[0]='s';
  printf("%s",p);
}
于 2011-02-28T06:42:31.547 回答
1

运行时机器中的内存是只读的,这完全无关紧要。在尝试通过 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); }

于 2011-02-28T06:43:14.257 回答
0

用于“amit”的内存不仅是可读的,而且这是依赖于编译器的天气,我们可以在位置 p[0] 上重写或不重写。我在 (GCC) 4.1.2 中也观察到了同样的情况。是的,它的预期输出和它的未定义的行为...

于 2016-01-28T07:15:08.330 回答