fgets
次のような(たとえば、here )の使用法をいくつか見てきました。
char buff[7]="";
(...)
fgets(buff, sizeof(buff), stdin);
興味深いのは、「aaaaaaaaaaa」のような長い入力をfgets
指定すると、7 番目の文字が'\0'
.
ただし、これを行う場合:
int i=0;
for (i=0;i<7;i++)
{
buff[i]='a';
}
printf("%s\n",buff);
私は常に 7'a'
秒を取得し、プログラムはクラッシュしません。'a'
しかし、8 sを書こうとすると、そうなるでしょう。
後で見たように、この理由は、少なくとも私のシステムでは、char buff[7]
( の有無にかかわらず=""
) を割り当てると、8 番目のバイト (0 からではなく 1 から数えます) が 0 に設定されるためです。このように正確に行われるため、for
7 回の書き込みとそれに続く文字列形式の読み取りを含むループは、最後に書き込まれる文字があったかどうかに関係なく成功'\0'
し、プログラマーが最後の '\0 を設定する必要がなくなります。 ' 自分自身、文字を個別に書き込む場合。
このことから、
fgets(buff, sizeof(buff), stdin);
長すぎる入力を提供すると、結果のbuff
文字列には自動的に 2 つの'\0'
文字が含まれます。1 つは配列内にあり、もう 1 つはシステムによって書き込まれた直後です。
私はまた、そのことを観察しました
fgets(buff,(sizeof(buff)+17),stdin);
引き続き動作し、クラッシュすることなく非常に長い文字列を出力します。私が推測したところ、これは がfgets
まで書き込みを続けsizeof(buff)+17
、最後に書き込まれる char が正確に a になり、'\0'
今後の文字列読み取りプロセスが適切に終了することを保証するためです (ただし、メモリはめちゃくちゃになります)。
しかし、ではどうfgets(buff, (sizeof(buff)+1),stdin);
ですか?これにより、 で正当に割り当てられたすべてのスペースが使い果たされbuff
、その後に'\0'
右側が書き込まれるため、'\0'
以前にシステムによって書き込まれたスペースが上書きされます。言い換えれば、はい、fgets
範囲外になりますが、書き込みの長さに 1 つだけ追加すると、プログラムがクラッシュすることは決してないことが証明できます。
最後に、ここで疑問が生じます:配列の直後にシステムによって配置された別のが既に存在fgets
しているのに、 は常に で書き込みを終了するのはなぜですか? 何も危険にさらすことなく、配列全体にアクセスし、プログラマーが必要とするものを何でも書き込むことができる、1 つずつループベースの書き込みのようにしてみませんか?'\0'
'\0'
for
ご回答どうもありがとうございました!
'\0'
編集: 確かに、 buff[7] の割り当て時に不思議なことに現れるこの 8 番目が、特に文字列配列の場合に C 標準の一部であるかどうかがわからない限り、可能な証拠はありません。そうでない場合は...それが機能するのはただの運です:-)