2011-12-30 118 views
0

以下兩個代碼片段編譯時沒有任何錯誤/警告,但運行時崩潰。請賜教。指向字符串的指針

程序1個

int main() 
{ 
    char *p= "Hello" ; 

    *p = 'B' ; 
    printf("\n%s",p); 

    return 0; 
} 

計劃2

int main() 
{ 
    char *p= "Hello" ; 
    Char *q="mug" 
    *q = *p ; 
    printf("\n%s",q); 

    return 0; 
} 

對於節目2 I期望輸出是 '擁抱'。

回答

8

當你這樣做:

char *p= "Hello"; 

您正在定義一個字符串。字符串文字是不變的數據,正如你發現的那樣,修改它們會導致未定義的行爲(通常是崩潰)。它應該被聲明爲:

const char *p = "Hello"; 

因此,如果您嘗試修改它,編譯器會引發錯誤。

現在,如果你定義它不是作爲:

char p[] = "Hello"; 

的內存,然後在棧上分配的,你可以修改它。

int main(int argc, char *argv[]) 
{ 
    char p[] = "Hello" ; 

    *p = 'B' ; 
    printf("\n%s",p); 

    return 0; 
} 

輸出Bello

的方案2,注意只q需要在堆棧上。 p可以保持指向字符串文字的const指針,因爲您只是從中讀取數據。

int main() 
{ 
    const char *p = "Hello" ; 
    char q[] = "mug"; 
    *q = *p ; 
    printf("\n%s",q); 

    return 0; 
} 

輸出Hug

+0

喬感謝隊友 – intex0075 2011-12-30 18:13:25

+0

@ intex0075很高興幫助,並感謝接受。 – JoeFish 2011-12-30 18:16:10

0

在這兩個示例中,您正在修改字符串文字,這會產生未定義的行爲。

0

你應該寫的是:

char p[] = "Hello"; 

上面的表格(字符P [] =「你好」)告訴編譯器,「我有值的來了一個陣列,請分配儘可能多的他們需要的空間。「它也適用於整數,例如:

int i [] = { 1, 2, 5, 100, 50000 }; 

您將最終與我是一個指向5值的數組的指針。

+0

是的,我意識到不久之後,我發佈並刪除它。對困惑感到抱歉。 – user1118321 2011-12-30 18:01:06

0

當您以char * p =「test」的形式創建靜態字符串時,指針的內容無法更改。在你的情況下,試圖修改指針的內容會導致你正在觀察的錯誤。

0

我將程序2更改爲不使用字符串文字。它顯示「擁抱」,如你所料。

#include <string.h> 
#include <stdio.h> 

int main() 
{ 
    char p[10]; 
    char q[10]; 
    strcpy(p,"Hello"); 
    strcpy(q,"mug"); 
    *q = *p ; 
    printf("\n%s",q); 

    return 0; 
} 
+0

這是一個答案? – 2011-12-30 17:59:12

+0

已經有4個答案爲什麼代碼失敗了。這個答案解釋瞭如何做對。 – 2011-12-30 18:02:38

0

字符串「你好」和「杯子」存儲在只讀存儲器和你試圖寫在那裏。

$ gcc -S a.c 
$ cat a.s 
    .file "a.c" 
    .section  .rodata 
.LC0: 
    .string "Hello" 
.LC1: 

請注意,該部分是「rodata」(只讀數據)。

+0

Atom是否表示文字存儲在「代碼/文本片段」中。這就是爲什麼它變成RO? – intex0075 2011-12-30 18:14:50

+0

文字存儲在包含數據(不是代碼)的部分「.rodata」中,ELF可執行文件中的標誌表示該部分是隻讀的。還有其他部分,如「.text」和「.data」。您可以使用「readelf --sections executable_file」打印所有部分,「Flg」列指定部分的訪問權限。 – 2011-12-30 18:24:38