2011-12-30 91 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