2012-03-06 216 views
0

我有以下程序要进行段错误。我无法理解为什么。请帮助我。C指针,seg故障

int main(){ 
    char *a="String One", *b="String Two"; 
    while(*a++=*b++); 
return 0; 
} 

为了分析它,我删除了while循环并使其更简单。它仍然给段错误!

int main(){ 
    char *a="String One", *b="String Two"; 
    *a++=*b++; 
return 0; 
} 

但是这个工作。我的意思是没有段错误!

int main(){ 
    char *a="String One", *b="String Two"; 
    *a++; 
    *b++; 
return 0; 
} 

回复Luchien:

我其实是试图效仿的strcpy。像这样的东西。现在,我知道字符串文字是只读的,我可以得到这个工作。谢谢你们。

main(){ 
char x[10]; 
char *xx = x; 

char *y = "Hello"; 

char *t=x, *f=y; 

while(*xx++ = *y++); 

printf(" %s ...%s \n",t,f); 
} 
+5

未定义的行为**更改**字符串文字。 http://c-faq.com/strangeprob/strlitnomod.html – cnicutar 2012-03-06 07:34:28

+0

还有未定义的行为在两个序列点之间写入两次相同的变量。 – martiert 2012-03-06 07:46:42

回答

0

你修改字符串常量,这是未定义行为

我也觉得烦人,

char *a="String One" 

实际上是

const char *a="String One" 

"StringOne"存储在只读存储器中,因此不能修改。

+0

在循环中使用赋值是复制字符串的C语言,请参阅K&R第5章 – Cameron 2012-03-06 07:43:53

+3

字符* may *可以存储在只读存储器中,这不是必需的,有些实现会实际更改字符串的内容,尽管不会阻止它是未定义的行为。 – dreamlax 2012-03-06 07:49:03

4

随着

char *a="String One", *b="String Two"; 

a点只读存储器包含给定的字符串。修改这是未定义的行为。

+0

哦。我不知道这是只读内存。非常感谢。 – Pkp 2012-03-06 07:38:55

0

当您通过说char *a="String One"创建字符串常量'a'不是一个数组,而是一个初始化为指向字符串常量的指针。如果你想改变它指向的字符串,你可以将它指向别处,但试图修改内容会导致未定义的行为。

3

许多操作系统将字符串值存储在只读内存部分,这意味着尝试修改内存导致操作系统告诉程序:嘿,你不能触及!在unix系统上,操作系统通过向进程发送SEGV信号来做到这一点,这通常会导致进程终止。由于C程序在裸机嵌入式系统和许多不同的操作系统上运行,其中一些具有此限制,其中一些不具有此限制,C标准声明此未定义的行为

0

在第三段代码中,*a++将访问由a指向的地址,该地址包含字符'S',因此没有段错误。

+0

这据我所知是因为字符串文字的起始地址存储为堆栈变量,而字符串文字是在只读部分。如果我做* a ++,那么我只是修改本地堆栈变量来指向不同的地址。所以它正在工作。我的理解是否正确? – Pkp 2012-03-06 07:57:20

+0

我认为你是对的,你只是修改指针'a'。 – 2012-03-06 08:10:34

0
while(*xx++ = *y++); 

这真的是你想要的吗?你想完成什么?这实际上是未定义的行为,因为你不知道在这之后会有什么xx。你会首先增加xx,还是先将y的值复制到xx,然后增加?见http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf 6.5。2

+0

我没有看到你的观点。 Postfix'++'的优先级高于取消引用'*'的优先级,所以它增加了指针变量而不是它的目标。并且在使用变量后发生递增,所以访问发生在旧点。 – glglgl 2012-03-06 14:40:50

+0

是的。我试图模仿strcpy,但是实现了你刚才告诉的信息。但是后来却非常涉及为什么字符串文字是只读的。 – Pkp 2012-03-07 02:59:47

0

a,b存储在数据段中的那些字符串。该部分是只读区域。所以你不能修改数据部分的字符串。 a和b只是指向数据部分的点字符串的指针。 x存储在堆栈中,所以你可以修改它。