1

与えられた文字列、例えば、

char *str = "Hello,StackOverflow!"
char newStr[30];
int l = strlen(str);
for(int i =0 ; i<l ; i ++ )
   newStr[i] = str[i];
printf("%s" , newStr);

これで、c-stringの最後の文字はである必要があることがわかりました。'\0'ここでは明示的に同じことを行っていないため(文字列newStrの最後のインデックスに'\ 0'を格納)、printfはクラッシュしないため、このプログラムはクラッシュするはずです。文字列の終わりを見つけます。

しかし、私はそれが時々うまく機能していることに気づきました、そして時々それはそうではありませんでした。何が問題なのか?実際にはほぼ毎回動作していました。クラッシュしたり、実行時エラーが発生したりすることはありませんか?

C ++でも同じでしょうか?

4

6 に答える 6

7

いいえ。未定義の動作を呼び出します。つまり、クラッシュする必要はありません。鼻の悪魔のように、文字通り何でもできます。

また、「ランタイムエラーが発生します」-まあ、それはランタイムエラーが何を意味するかによって異なります。Cには動的なランタイムはありません。例外から適切にフォーマットされたエラーメッセージが期待される場合、それは起こりません。何が起こるかは、おそらくセグメンテーション違反です。

全体として、未定義の動作を引き起こしたり使用したりする場合、クラッシュしたりクラッシュしたりしないことに依存してはなりません。

于 2012-09-17T16:17:48.710 に答える
3

「クラッシュ」は保証されません。文字列内のヌルターミネータを不適切に処理するプログラム(より一般的にはバッファ境界の外側のデータにアクセスする)、または printfフォーマット文字列に違反するプログラムは、正常に機能し、機能しており、セグメンテーション違反を引き起こさないように見える場合があります。しかし、これは単なる偶然です。コードの動作は未定義です。

C++でも同じです。

于 2012-09-17T16:17:43.473 に答える
2

ほとんどの場合、「!」を超えて印刷し続けるのではないかと思います。NULLに達するまでメモリ内に移動し続けます。クラッシュする可能性がありますが、そうする必要はありません。

これが、次のいずれかに最適な理由です。

memset(newStr, 0, 30);

また

// This works because string literals guarantee a '\0' is present
// but the strlen returns everything up until the '\0'
int l = strlen(str) + 1;

これも機能しますが、strlenに1つ追加するほど明確ではないと思います。

for(i =0 ; i<=l ; i ++ )

strlenの定義は、そうする必要があることを意味します。

于 2012-09-17T16:27:35.860 に答える
1

偶然にも、ほとんど場合、初期化されていないバイトは特定のケースにあります。newStr0

于 2012-09-17T16:17:45.340 に答える
1

nullで終了する文字列printfへのポインタを使用して呼び出すことを約束しているが、そうしなかったため、プログラムの動作は未定義です。何かが起こる可能性がありますが、あなたのプログラムは単に正しくありません。

具体的には、配列要素を1つずつ読み取ってヌルターミネータを見つける間、プログラムは最終的に初期化されていない変数であるUBにアクセスします。

于 2012-09-17T16:19:05.780 に答える
0

文字として初期化されていないバイトを読み取る動作は、Cのほとんどの実装では定義されていません。printfがガベージを書き込む場合や、プログラムが最後の文字の後にヌルバイト\ 0を見つけて、正常に終了する場合があります。まれに、クラッシュが発生する場合があります。これが、プログラムを実行したときに何が起こるかについて変化が見られる理由です。これは、使用しているコンパイラと、アレイに割り当てた後のメモリ位置に何があったかによって異なります。

(つまり、プログラムがコンパイルされる場合は、セミコロンを省略しました)

于 2012-09-17T16:21:21.493 に答える