次のコードで正確に何が起こっているかを理解するのに役立ちますか? (「a」の代わりに「a」と書くなど...)。つまり、メモリに保存されるものと、プログラムがクラッシュしない理由です。
char str[10] ;
str[0] = "a";
str[1] = "b";
str[2] = "\0";
ありがとう。
C では許可されていますが、期待どおりの動作はしません。最初のもの (str[0]
および"a"
) について、コンパイラが行うことは、コンパイラが作成する文字配列を"a"
変換してポインターに減衰させ、次にこのポインターを に変換することchar
です。
したがって、格納されるのは、文字列リテラルの配列のアドレスstr[0]
の最後のバイトです。"a"
'a' はchar
、ASCII 値 97 を持つ単一の文字 (タイプ ) です。「a」は C スタイルの文字列でありchar
、'a' と '\0' の 2 つの要素を持つ配列です。
上記のコードをコンパイルすると、3 つの割り当てに対して 3 つの警告が表示されます。GCC では、これらの警告は次のように表示されます。
main.c:6:12: warning: assignment makes integer from pointer without a cast [enabled by default]
コードの最初の代入を取りましょう:
str[0] = "a";
右側のオペランド "a" は achar *
です。左側のオペランドは achar
で、整数型です。警告が示唆しているように、ポインターの値を取得し、整数に変換してから、サイズにchar
切り捨て、切り捨てられた値を に格納しstr[0]
ます。そのため、代入後、str[0]
期待どおりに値 'a' (ASCII 97) は含まれませんが、上記のように値が取得されます。
これまでのところ、プログラムがクラッシュする理由はありstr
ません。意味のある文字列が含まれていないことに注意してください。
たとえば、その文字列を印刷するなど、何か便利なことをしようとすると、次のようになります。
printf("%s", str);
プログラムをクラッシュさせる可能性のある理由を見つけます (または、メモリの破損など、他の多くの問題を引き起こす可能性があります)。問題は、最後の代入である が、str[2] = "\0"
期待どおりに文字列を適切に終了しないことです。したがって、適切に NULL で終了しない C スタイルの文字列になってしまいます。これは災害への確かな近道です。
この動作をテストするにはstr
、これらの割り当ての後に格納されている実際の値を表示してみてください。
printf("%d - %d - %d", str[0], str[1], str[2]);
ほとんどの場合、予想とは異なる値 (97、98、0) が表示されます。
単純化した用語... これを例にとります。-文字列は基本的に文字の配列のようなものです。-チャーは小物のようなものです。「a」は文字で、「a」は文字列です。言い換えると、'a' は knick-knack であり、"a" は knick-knack 'a' を含むラックです。Str[10] は 10 個の棚があるラックです。これを行うと、 Str[0] = "a"; 小物「a」が入ったラックを別のラックの最初の棚に押し込むようなものです...
つまり、ラック全体を別のラックに押し込んで、それが収まることを期待するようなものです...
この答えに論理がまったくない場合でも、それを示すだけです。 str[0] = "a"; もまったく意味がありません。str[0] = 97; を実行することもできます。引用符を完全に忘れるため.. :P