C には、ネイティブの文字列型がありません。慣例により、言語はchar
null char で終了する の配列、つまり with を使用します'\0'
。言語の標準ライブラリの関数とマクロは、null で終わる文字配列のサポートを提供しchar
ます。'\0'
'\0'
C でのヌル終了文字列の使用は、C がアセンブリ言語よりも少しだけ高レベルになることを意図していたという事実を反映しています。PDP-10 および PDP-11 のアセンブリ言語では、その時点ですでにゼロ終了文字列が直接サポートされていました。
C 文字列のこの特性は、重大なセキュリティ上の欠陥を含む、かなりの数の厄介なバッファ オーバーラン バグを引き起こすことに注意してください。たとえば、ソース引数として に渡された文字列を null で終了するのを忘れた場合strcpy
、関数は、ソース文字列の末尾を過ぎてメモリ内にあるものから順次バイトをコピーし続け0
ます。メモリ内の宛先文字列の場所に続く貴重な情報。
あなたのコード例では、文字列リテラル "Hello, world!" の 14 バイト長の配列にコンパイルされますchar
。最初の 13 バイトには、文字、コンマ、スペース、感嘆符が含まれ、最後のバイトには'\0'
、コンパイラによって自動的に追加されるヌル終了文字が含まれます。配列の最後の要素にアクセスすると、 と等しいことがわかります0
。例えば:
const char foo[] = "Hello, world!";
assert(foo[12] == '!');
assert(foo[13] == '\0');
ただし、あなたの例では、message
長さはわずか 10 バイトです。strcpy
はヌル ターミネータを含む 14 バイトすべてを のアドレスから始まるメモリに書き込みますmessage
。最初の 10 バイトはスタックに割り当てられたメモリに書き込まれmessage
、残りの 4 バイトは単にスタックの最後に書き込まれます。この場合、これらの 4 バイトをスタックに書き込んだ結果を予測するのは困難ですが (この単純な例では、問題は発生しない可能性があります)、実際のコードでは通常、データの破損やメモリ アクセス違反のエラーが発生します。