34

次のコード スニペットのように、文字列を文字配列に割り当てるために strcpy() が必要な理由を説明してください。

int main(void) {

char s[4];

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

return 0;
}

s = "abc"失敗する理由とは?そして、なぜ strcpy() は、文字列が宣言された後に char 配列に文字列を代入する唯一の方法なのですか? 基本的な割り当てを実行するために関数を使用する必要があるのは奇妙に思えます。

4

4 に答える 4

34

C の配列は、代入もコピー初期化もできません。これが C における配列のあり方です。歴史的に、値のコンテキスト (割り当ての右辺) では、配列はポインターに減衰します。これは、配列だけでなく、すべての配列に適用されcharます。

C 言語は、その前身である B および BCPL 言語からこの配列の動作を継承しています。これらの言語では、配列は物理ポインターで表されていました。(また、ある配列を別の配列に代入するときに、ポインターの再代入が発生することを望まないことは明らかです。) C 言語の配列はポインターではありませんが、減衰によって B および BCPL 配列の歴史的な動作を「シミュレート」します。ほとんどの場合、ポインターに。この歴史的遺産が、今日まで C 配列をコピー不可能にしている理由です。

上記の 1 つの例外は、文字列リテラルを使用した初期化です。つまり、できる

char c[] = "abc";

この場合、概念的には文字列リテラルを配列にコピーしています。もう 1 つの例外は、構造体オブジェクト全体がコピーされるときにコピーされる、構造体型にラップされた配列です。そしてそれはそれについてです。"abc"c

これは、ネイキッド (ラップされていない) 配列をコピーするときはいつでも、ライブラリ レベルのメモリ コピー関数 ( memcpy. strcpyは、文字列で動作するように特別に調整されたものの単なるフレーバーです。

于 2011-08-01T16:02:34.217 に答える
14

それは単にCの配列です。それらに割り当てることはできません。必要に応じてポインタを使用できます。

char *p;
p = "abc";

ちなみにC FAQがあります。

C では、配列は「二流市民」です。この偏見の結果の 1 つは、それらに割り当てることができないということです。

于 2011-08-01T16:00:36.030 に答える
3

簡単な答え: 歴史的な理由。C には組み込みの文字列型がありませんでした。std::string が誕生したのは C++ が登場してからであり、それでさえ最初の実装では実現しませんでした

長い答え: 「abc」の型はchar[]ではなくchar *です。strcpyポインターが指すデータ (この場合は ABC) をコピーできるメカニズムの 1 つです。

strcpy配列を初期化する唯一の方法ではありませんが、文字列の末尾にある 0 を検出して尊重するのに十分スマートです。memcpyを使用して文字列をコピーすることもできますが、コピーsするデータの長さを渡す必要があり、終端の 0 (NULL) が存在することを確認する必要がありますs

于 2011-08-01T16:02:41.287 に答える