2009-11-20 43 views
14
char數組和指針用C

所以,我有下面的程序:分割故障原因在Linux

int main(){ 
    char* one = "computer"; 
    char two[] = "another"; 
    two[1]='b'; 
    one[1]='b'; 
    return 0; 
} 

它出現segfaults上這是有意義的行「一個[1] =‘B’」,因爲存儲器「one」指針必須位於只讀存儲器中。然而,問題是爲什麼不行「two [1] ='b'」段錯誤?查看gcc的彙編輸出:

.file "one.c" 
     .section  .rodata 
.LC0: 
     .string "computer" 
.LC1: 
     .string "another" 
     .text 
.globl main 
     .type main, @function 
main: 

我們看到兩個字符串都位於rodata節中,因此它們是隻讀的。那麼爲什麼線「two [1] ='b'沒有段錯誤?

+0

也看到了不同,但相關的問題http://stackoverflow.com/questions/ 1770067 /定義指針到靜態字符串/ 1770067#1770067 – 2009-11-20 20:43:14

回答

35

one直接指向位於只讀頁面的字符串另一方面,two是一個在堆棧上分配的數組並用一些常量數據初始化,在運行時,可執行文件的只讀部分中的字符串將被複制到堆棧中,您正在修改的是該堆棧中該字符串的副本,而不是隻讀存儲器頁面。

在較高的水平角度,從語言角度,"abcd"const char*類型和表達式不char*。因此,修改由不確定的行爲這樣的表達式的結果指出的值。該語句char* one = "something";僅將指向字符串的指針存儲在變量中(不安全,因爲它正在丟棄const修飾符)。 char two[] = "something";是完全不同的。它實際上是聲明一個數組並初始化它,就像int a[] = {1,2,3};。這裏引號中的字符串是初始化表達式。

+3

哇...我已經在C編程了大約5年,現在我不知道'char []'做了一個常量數據的副本。我一直認爲''''是寫'*'的更好的方法。謝謝! +1 – Earlz 2009-11-20 20:39:52

+3

我經常寫'char str [] = {「Something」};'試圖使關聯更清晰。 – LnxPrgr3 2009-11-20 21:01:30

+0

@ Mehrdad:水晶般清澈! :) – 2012-06-20 17:20:06

1

您在rodata部分看到的「另一個」將在數組two中被初始化時被複制。另一方面,字符串「computer」的地址將被分配給一個。

因此,one指向一個只讀段(因此寫入時段錯誤),而two將被分配到堆棧,然後將「另一個」複製到它。

0

第二種形式通過複製文字字符串來創建數組。

它等效於:

char two[] = {'a', 'n', 'o', 't', 'h'. 'e', r', '\0'}; 

可以初始化字符數組變量,如

char c = 'a'; 
char two[] = {'a', 'n', c, '\0'};