3

今日は奇妙な問題に遭遇しましたprintf()。しかし、分析しても答えは見つかりませんでした。したがって、ここで共有します。printf()私はこれらの3つのステートメントを試しました:

printf("\nValue of this division is %f", (double)873/(double)65);

期待どおりに正しい出力を出力します。

printf("\nSome message with an integer here %d followed by floats %f, %f, %f", 2013, 987/432, 873/65, 983/81);

間違った値を与えられた (double にキャストしなかったためか?)

printf("\nSome message with an integer here %d followed by floats %f, %f, %f and now string at end: %s", 2013, 987/432, 873/65, 983/81, "Some trial string here");

printf()ここで墜落!そして、これは私に2つの質問を提起します:

  1. MSDN で提供されている "FormatOutput(LPCSTR formatstring, ...)" の例を見ました。この例では、固定幅の宛先バッファーを割り当ててから呼び出しますvsnprintf()printf()私は同じ線に沿って動作すると信じています。しかし、内部バッファサイズがどこにも見つかりませんでしprintf()た。メモリを動的に割り当てる場合、バッファ サイズをどのように計算しますか?

  2. printf()上記の行でvsnprintf()もクラッシュするため、クラッシュします(はい、上記のパラメーターでFormatOutput指定されたサンプルコードを試しました)。vsnprintf()しかし、なぜ最終的にクラッシュするのでしょうか?

4

5 に答える 5

2
printf("\nSome message with an integer here %d followed by floats %f, %f, %f and now string at end: %s", 2013, 987/432, 873/65, 983/81, "Some trial string here");

以前の回答で説明したように、整数除算の結果は整数です。その987/432ため、システムは(ほとんどの場合) 32 ビットintになります。しかし、64ビットを期待するように%f指示します! したがって、 と の結合されたメモリ空間を読み取ります- ガベージ結果を出します。それに続いて、別の 64 ビットの:と- へのポインターが再びゴミになります。printfdouble987/432873/65double983/81"Some..."

別の 64 ビット double (3 番目の%f) が続きますが、これは範囲外です! 2 番目の例がすぐにクラッシュしなかったのは、おそらく幸運です。に達するまでに%sprintf()ポインターを探します...境界外アクセスからクラッシュしない場合は、結果のポインターの無効なメモリアドレスにアクセスしようとします。

  1. printf()メモリを割り当てる必要はありません。標準出力(端末ウィンドウなど)に直接書き込みます

  2. ファミリのバリエーションは、printfまったく同じようにクラッシュします。

于 2013-09-02T23:09:39.083 に答える
2

あなたの引数 `2013, 987/432, 873/65, 983/81' はすべて int です!

于 2013-09-02T19:59:50.620 に答える
2

あなたの例では、printf (...)倍精度浮動小数点が予想されるときに整数除算の結果を提供しています。単精度または倍精度の浮動小数点除算を使用するか、書式文字列を修正してください。可変引数リストと組み合わせて使用​​すると、char と short が int に昇格されるのと同様に、単精度浮動小数点は自動的に倍精度に昇格されることに注意してください。

思考実験として、ポインターを 32 ビット データ型から 64 ビット型にキャストし、逆参照を試みるという架空のシナリオで発生する可能性のある無数のことを考慮する必要があります。上記のポインター シナリオと同様に、データ型を不適切に伝達した結果として、未定義の動作に対処しています。未定義の動作を呼び出すと、発生してプログラムがクラッシュする可能性のある厄介なことがいくつかあります。

それにもかかわらず、一部のコンパイラは、コンパイル時にフォーマット文字列を解析し、指定した引数のリストに対して検証することができますprintf (...)。システムで利用可能なコンパイラ警告を調べて、将来これを回避できるようにすることをお勧めします。

于 2013-09-02T20:11:03.607 に答える
2

または(double)873/(double)65を使用するだけで、キャストに使用する必要はありません。をan で割ると、常に値になります。印刷するには、または 単に印刷するために を使用できます。どちらも機能します。(double)873/65873.0/65intintintdouble987.0/432987f/432float

于 2013-09-02T20:06:19.647 に答える