2011-08-01 26 views
20

文字列を文字列に割り当てるためにstrcpy()が必要な理由を以下のコードスニペットで説明してください。C - なぜstrcpy()が必要なのですか?

int main(void) { 

char s[4]; 

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

return 0; 
} 

s = "abc"が失敗する理由は何ですか?そして、なぜ文字列が宣言された後でchar配列に文字列を割り当てる唯一の方法はstrcpy()ですか?基本的な割り当てを行うために関数を使用しなければならないということは私にとっては奇妙なことです。

答えて

12

これはCの配列が単純にどのようなものかを示しています。割り当てはできません。

char *p; 
p = "abc"; 

。なお、C FAQがあります:あなたが好きな場合は、ポインタを使用することができます。

配列はC言語の「第2種市民」です。この の偏見の1つの結果は、に割り当てることはできません。

+0

ええ私はポインタを使用して、私はちょうどs = "abc"が私の例では動作しない理由を理解していない。 sは文字配列で、 "abc"も同様です... –

+4

@ C_p678 - いいえ、 's'は文字配列です、" abc "は定数文字列へのポインタです。 – MByD

+3

@MByD:完全には正しくありません。 '' abc ''はポインタではありません。 '' abc''型の配列 'char [4]'は、この文脈では 'char *'型のポインタに崩壊します。 Cの文字列は定数ではないことに注意してください。これは変更不可能ですが、型自体には 'const'修飾子は含まれていません。 – AnT

24

Cの配列は割り当て不可であり、コピーを初期化できません。これは、配列がCでどのように行われるかということです。伝統的には、値のコンテキスト(代入のRHS上)では、代入やコピー初期化を正式に阻止するポインタが配列に分解されます。これはすべての配列に適用され、char配列だけでなく

C言語は、この配列動作をその前身であるB言語およびBCPL言語から継承します。これらの言語では、配列は物理的なポインタで表されていました。 (そして、明らかにポインタの再割り当ては、ある配列を別の配列に割り当てるときに起こりたいことではありません。)C言語の配列はポインタではありませんが、BおよびBCPL配列の崩壊による履歴動作を "シミュレート"しますほとんどの場合、ポインタに変換します。この歴史的な遺産は、今日までC配列をコピー不可能にするものです。

上記の例外の1つは、文字列リテラルによる初期化です。私。することができます

char c[] = "abc"; 

しかしそれはそれです。

これは、配列をコピーしたい時はいつでも、あなたはmemcpyのように、ライブラリレベルのメモリコピー機能を使用する必要があることを意味します。 strcpyは、文字列で動作するように特別に調整されたものです。

+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)をコピーできる1つのメカニズムです。

strcpyアレイを初期化する唯一の方法ではない、しかし、文字列の末尾で終端0を検出し、尊重するのに十分スマートです。 C言語は、任意の便利な構文を欠いs

+3

'' abc ''の型は' char [4] 'です。 –

+3

'strcpy'は初期化ではなく代入です。文字配列は他のすべての配列として初期化できます。AndreyTの答えを見てください。 –

0

に存在しているあなたもsに文字列をコピーするmemcpyを使用することができますが、それはあなたが、コピーするデータの長さを渡す必要があり、終了0(NULL)を確保するために長さの指示と共に文字列リテラルへのポインタを得るためのものです。多くのパスカル方言を含むいくつかの言語では、各文字列の先頭にその長さを示すバイトが付いています。これは多くの目的でうまく機能しますが、文字列リテラルは255文字に制限されます。 Cのアプローチでは、任意の長さの文字列リテラルを収容できますが、長さに関係なく1バイトのオーバーヘッドしか追加しません。

ゼロで終わる文字列は、ほとんどすべての目的の文字列リテラル以外ための他の形態に比べて劣っているが、リテラルは多くのプログラムが対処しなければならないこと、これまでと離れて、文字列の最も一般的な形式であるため、そこにありますライブラリ関数を効果的に扱うことに大きな利点があります。ゼロ終端された文字列を他の型のライブラリルーチンの個別の集合よりも理想的でない場合に使用する方が簡単になります。

関連する問題