2011-08-01 140 views
20

有人可以向我解釋爲什麼需要strcpy()將字符串分配給字符數組,例如下面的代碼片段。C - 爲什麼需要strcpy()

int main(void) { 

char s[4]; 

s = "abc"; //Fails 
strcpy(s, "abc"); //Succeeds 

return 0; 
} 

s = "abc"失敗的原因是什麼?爲什麼strcpy()是在聲明後將字符串分配給char數組的唯一方法?我覺得你不得不使用一個函數來執行基本任務。

回答

12

這就是C中的數組。你不能指定給它們。如果你喜歡,你可以使用指針:

char *p; 
p = "abc"; 

順便說一下,有一個C FAQ

數組是C中的「二等公民」;這個 偏見的結局是你不能分配給他們

+0

是的,我使用指針,我只是不明白爲什麼s =「abc」在我的例子中不起作用。 s是一個char數組,「abc」也是...... –

+4

@ C_p678 - 不,s是一個char數組,「abc」是一個指向常量字符串的指針。 – MByD

+3

@MByD:不完全正確。 ''abc「'不是一個指針。 ''abc''是一個'char [4]'類型的數組,在這種情況下,它會衰減到一個'char *'類型的指針。請注意,在C中,字符串不是常量。它是不可修改的,但類型本身不包含'const'限定符。 – AnT

24

C中的數組是不可分配的和不可複製初始化的。這就是數組在C中的樣子。從歷史上看,在值的上下文中(賦值的RHS)數組會衰減到指針,這正是阻止賦值和複製初始化的原因。這適用於所有陣列,不僅適用於char陣列。

C語言從它的前輩-B和BCPL語言中繼承了這種數組行爲。在這些語言中,數組由物理指針表示。 (顯然,當你將一個數組分配給另一個數組時,指針的重新賦值並不是你想要發生的。)在C語言中,數組不是指針,但它們通過衰減「模擬」B和BCPL數​​組的歷史行爲指針在大多數情況下。這個歷史遺產是讓C陣列不可複製到今天。

從上面的一個例外是用字符串文字初始化。即你可以做

char c[] = "abc"; 

但就是這樣。

這意味着無論何時要複製數組,都必須使用庫級複製功能,如memcpystrcpy只是專門爲字符串工作而設計的。

+1

爲了澄清,所有的數組類型都可以用'{val0,val1,...}'形式的適當的初始化方法初始化。 –

+0

你不*有*使用庫函數;您可以分配單個字符,例如'for(char * dst = s,* src =「abc」; * dst ++ = * srC++;);'。儘管庫函數是一個更好的選擇,因爲它更易於閱讀,並且可以針對系統進行優化。 –

+1

是的,要更多地瞭解@AnT所說的內容,'strcpy()'幾乎和'memcpy()'完全一樣,只是它包含空字節。 – RastaJedi

1

簡答:歷史原因。 C從來沒有內置的字符串類型。直到C++出現,std :: string應運而生,甚至在第一次實現時沒有到達。

長答案:「abc」的類型不是char[],而是char *strcpy是一個可以複製指針指向的數據的機制(在這種情況下,這是ABC)。

strcpy不是初始化數組的唯一方法,但是,它足夠聰明,可以檢測並尊重字符串末尾的終止0。您也可以使用memcpy將字符串複製到s中,但需要傳入要複製的數據的長度,並確保終止0(NULL)存在於s

+3

''abc「'的類型是'char [4]'。 –

+3

而'strcpy'不是一個初始化,而是一個賦值。字符數組可以初始化爲所有其他數組,請參閱AndreyT的答案。 –

0

C語言缺少任何方便的語法用於獲取指向字符串的指針以及其長度的指示。包括許多Pascal方言的一些語言在每個字符串前加上一個報告其長度的字節;這適用於很多目的,但將字符串文字限制爲255個字符。 C的方法允許容納任何長度的字符串文字,但不管長度如何,只增加一個字節的開銷。

零結尾的字符串遜色於其他形式的幾乎每一個目的其他不是字符串文字,但文字是如此遠和字符串的最常見的形式,許多項目將需要處理,因此存在具有圖書館職能有效處理這些功能的相當大的優勢那麼在不太理想的情況下使用零終止字符串比爲其他類型創建單獨的一組庫例程變得更容易。