2011-12-30 51 views
1

我在某处找到了一个问题...这里是它的解释和答案。简单的C代码在gcc上给出分段错误

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'类似地改变为'b'等等。同样的空格被转换为'!'。因此,我们在p中获得的值变成“ibj!gsjfoet”,并且由于p到达'\ 0'并且p1指向p,因此p1不会打印任何东西。

我发现P1上的解释有问题,我认为P1应该打印“海朋友”,并且输出的p是正确的。

,但是当我试图运行gcc编译相同的代码,它给segmentatiion故障

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

#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应作为它的起始位置,即在字符串的起始地址。请如果有人能解释它在哪里,我得到它错了?

+1

这*必须*重复。懒得去搜索它。 – Tom 2011-12-30 18:01:26

回答

4

对于其中之一,应该避免这样的代码:++*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; 

} 
+0

谢谢...但如果可能的话,你可以解释一下更多..我的意思是如何工作?如果我将它声明为'指向char'的指针,则不允许我更改该字符串,但是如果将它作为一个charertrs数组,就可以做到这一点。其次我试图用你说的,但又一个错误'lvalue rquired'.Thanx提前! – 2011-12-30 17:55:37

+0

这是代码编译器的依赖? – 2011-12-30 17:56:27

+1

原因是声明为char * p =“blah”的字符串字面值存储在静态内存中,不允许修改。然而,当它被声明为'char p [] =“blah”时,它是'char p [] = {'b','l','a','h','\ 0'}的简写形式。 ;'这是堆栈上的一个数组,可以修改。 – Mysticial 2011-12-30 17:59:39

1

"hai friends"是一个字符串,不能修改。

+1

这是不正确的,因为示例程序确实修改了字符串。神秘是正确的,因为它是未定义的行为。在这种情况下,值会递增,但在其他系统上,行为可能会有所不同。如果数据在ROM中,则值不会改变,如果写入ROM,则硬件可能会产生中断。操作系统可能会将数据放入RAM的只读段(IIRC可以在ia32代码中完成),并在数据写入时产生运行时错误。或者完全是别的。 – Skizz 2011-12-30 18:01:53

+2

在这种情况下,“不能”的含义是“不允许的”。 – 2011-12-30 18:12:08