2012-03-06 167 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存儲在堆棧中,所以你可以修改它。