web-dev-qa-db-ja.com

文字列をchar *ポインターに割り当てることはできますが、char []配列には割り当てられないのはなぜですか?

誰かがこれがポインタで動作する理由を説明できますか?

char * str1;

str1 = "Hello1";

str1 = "new string";

// but not this
char str2 [] = "hello";
str2 = "four";

// or this
char str3 [];
str3 = "hello";
str3 = "hello";
61
nick

ポインタで動作する理由:
Cでchar * str1と言うと、メモリにポインタを割り当てています。 str1 = "Hello";を記述するとき、メモリ内に文字列リテラルを作成し、ポインタがそれを指すようにします。別の文字列リテラル"new string"を作成してstr1に割り当てると、ポインターが指す場所を変更するだけです。

なぜ配列で動作しないのか:
char str2 [] = "Hello"と言うとき、文字列リテラルを作成し、その定義中に配列に入れます。配列がサイズを計算し、'\0'を追加するため、サイズを指定しなくてもかまいません。サイズを変更せずにそのアレイに何かを再割り当てすることはできません。 str2 = "four"が機能しない理由です。

str3の場合、同じケースです。定義で配列のサイズを定義していないため、サイズを0に計算しました。配列のサイズを変更せずに新しいものを割り当てることはできません。

77
tryurbest

配列とポインターは異なるものです。そのためです。ポインターに割り当てることはできますが、配列に割り当てることはできません。文字列リテラルを使用したchar配列の初期化には、特別な例外が作成されます。

char a[] = "Hello"; //initialize a char array with string literal. Special case, OK
char* p = "Hello"; //initializa a pointer with an array(which gets converted to pointer)
p = "My";   //assign pointer to point to another value. OK
a = "My";   //error, arrays cannot be assigned to. Use `strcpy`

文字列リテラル(「Hello」など)のタイプはchar[N]ここで、Nは文字数です(終端の'\0')。配列は、その最初の要素へのポインターに変換できますが、配列とポインターは、悪い本や先生が言っても同じものではありません。

19
Armen Tsirunyan

簡単に言えば、配列はC/C++のファーストクラスオブジェクトではないためです。配列に割り当てる唯一の方法は、str(n)cpyまたはmemcpyを使用することです。

配列は関数に渡されるとポインタになりますが、初期化としてコンパイル時を除き、配列に割り当てることはできません。

7
Julian

ポインターの場合これは、str1="Hello"、実際にはhelloという名前の文字列リテラルを作成し、それをメモリのどこかに割り当て、リテラルの最初の文字のアドレスをポインターに割り当てます。ポインターは定数ではないため、別のアドレスで再度割り当てることができます。さらに重要な注意点は、作成される文字列リテラルが読み取り専用メモリにあることです。

文字配列の場合言語でサポートされているように、初期化中に文字列リテラルを割り当てることができます。また、割り当てと初期化を混同しないでください。代入中、その文字配列は文字ごとに値を変更する必要があるため、文字列リテラルの最初のアドレスを配列の最初の文字にアドレッシングしようとしています(配列の名前は、最初の要素のアドレスを返しますそして、最初の要素がポインターではないため、これは明らかに正しくありません。アドレスを保存できません。

3
joker007

これは単に、このコードを書くときの理由です。

char str2 [] = "hello";

あるいは:

int arr[] = {1,2,4,4,5};

str2またはarrを定数ポインターとして。そのため、これらのポインターに他の値を再割り当てすることはできませんが、後の場合は通常のポインターを作成し、任意の値を割り当てることができます。

3
Sawan