【问题标题】:simple C code giving segmentation fault on gcc在 gcc 上给出分段错误的简单 C 代码
【发布时间】:2011-12-30 17:45:24
【问题描述】:

我在某处发现了一个问题......在这里,它的答案带有解释。

main()
{
char *p="hai friends",*p1;
p1=p;
while(*p!='\0') ++*p++;
printf("%s   %s",p,p1);
}

 Answer:
 ibj!gsjfoet

 Explanation:
++*p++ will be parse in the given order

*p 是 p 当前指向的位置的值

++*p 检索到的值会递增

什么时候;遇到位置会递增即p++会被执行

因此,在while循环中,p指向的初始值为'h',通过执行++*p将其更改为'i',指针移动到指向'a'的点,'a'类似地更改为'b'和很快。类似地,空格被转换为“!”。因此,我们在 p 中获得的值变成了“ibj!gsjfoet”,并且由于 p 达到了“\0”并且 p1 指向 p,因此 p1 不打印任何内容。

我发现 p1 的解释有问题。我认为 p1 应该打印“hai friends”并且 p 的输出很好。

但是当我尝试在 gcc 编译器上运行相同的代码时,它给出了 segmentatiion fault

这是我尝试运行的确切代码..

 #include<stdio.h>
 int main()
 {
 char *p="hai friends",*p1;
 p1=p;
 while(*p !='\0') ++*p++;
 printf("%s   %s",p,p1);
 return 0;
 }

如果可以编辑标题,我找不到合适的标题来更清楚地说明情况。

编辑:

我尝试按照 Mysticial 的建议运行修改后的代码,但我认为输出应该是 -

ibj!gsjfoet    hai friends

因为我只增加 p0 但 p1 应该作为它的初始位置,即字符串的起始地址。请如果有人能解释一下我哪里弄错了???

【问题讨论】:

  • 这个必须是重复的。不过懒得找了。

标签: c string pointers gcc segmentation-fault


【解决方案1】:

首先,应该避免使用像这样的代码:++*p++,因为它通常很难阅读。

其次,问题在于您正在修改字符串文字。那是未定义的行为。不要这样做。

相反,将您的声明更改为:

char p[] = "hai friends";
char *p1;

并修改您的代码:

int main()
{

    char p[] = "hai friends";
    char *p0,*p1;
    p0 = p;
    p1 = p;
    while(*p0 !='\0') ++*p0++;
    printf("%s   %s",p0,p1);
    return 0;

}

【讨论】:

  • 谢谢......但如果可能的话,你能解释一下吗......我的意思是它是如何工作的???如果我将其声明为pointer to char,则不允许我更改字符串,但如果我将其设置为array of characetrs,我可以这样做。其次,我尝试按照您所说的那样使用它,但又出现了一个错误lvalue rquired.Thanx !
  • 原因是声明为char *p = "blah"的字符串字面量存储在静态内存中,不允许修改。但是,当它声明为char p[] = "blah"时,它是char p[] = {'b', 'l', 'a', 'h', '\0'};的简写,它是堆栈上的一个数组,可以修改。
  • 再次感谢...如果可能的话,请查看我的编辑,以便我可以清除我的错误并关闭线程。
  • 要回答您的新问题,请注意您仍然只有 1 个字符串副本。您的两个指针 p0p1 指向同一个字符串。 (尽管部分不同)所以当你修改p0的内容时,你也在修改p1的内容。如果要打印原始字符串,则需要在开始循环之前对其进行复制。
  • 啊,我刚试过,我发现了问题。 p1 实际上被打印为ibj!gsjfoetp0 没有被打印出来。那是因为在您的循环之后,p0 指向字符串的 end。第一个字符是\0。所以它实际上是一个空字符串。
【解决方案2】:

"hai friends" 是无法修改的文字字符串。

【讨论】:

  • 这不是真的,因为示例程序确实修改了字符串。神秘是正确的,因为它是未定义的行为。在这种情况下,值会增加,但在其他系统上,行为可能会有所不同。如果数据在 ROM 中,则值不会改变,如果写入 ROM,硬件可能会产生中断。操作系统可能会将数据放入 RAM 的只读段(IIRC 可以在 ia32 代码中完成),并在写入数据时生成运行时错误。或者完全是别的东西。
  • 在这种情况下,“不能”的意思是“不允许”。
猜你喜欢
  • 2012-11-19
  • 1970-01-01
  • 1970-01-01
  • 2022-12-18
  • 2011-12-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多