6

または、言い換えると: 間違ったprintf/ fprintf10 進整数 ( %d%u、 ) フォーマット文字列が原因で%ld%lldプログラムがクラッシュしたり、未定義の動作が発生したりする可能性はありますか?

次のコード行の Cosinder:

#include <iostream>
#include <cstdio>

int main() {
    std::cout << sizeof(int) << std::endl
              << sizeof(long) << std::endl;

    long a = 10;
    long b = 20;
    std::printf("%d, %d\n", a, b);

    return 0;
}

32 ビット アーキテクチャでの結果:

4
4
10, 20

64 ビット アーキテクチャでの結果:

4
8
10, 20

いずれにせよ、プログラムは期待される結果を出力します。long値が範囲を超えると、プログラムは間違った数値を出力することはわかっていますが、intこれは見苦しいですが、プログラムの主な目的には影響しません。

4

5 に答える 5

8

printf が間違ったフォーマット文字列で呼び出されるとどうなりますか?

何でも起れる。それは未定義の動作です!
未定義の動作とは、何でも起こり得ることを意味します。期待どおりの結果が表示されるか、表示されないか、クラッシュする可能性があります。何でも起こり得るし、それについて自分以外の誰を責めることもできません。

参照:

c99 標準: 7.19.6.1:
パラ 9:

変換指定が無効な場合、動作は未定義です。225)いずれかの引数が対応するカバー指定の正しい型でない場合、動作は未定義です。

于 2013-01-24T14:53:48.527 に答える
3

これは未定義の動作です。仕様には、コンパイラ設計者 (または C ライブラリ設計者) にこれをどのように処理するかを指示するものは何もないため、彼らは何でもすることができます。

実際には、数値の解釈に完全に依存するものの 1 つであり、これを行っても何も得られない可能性が最も高いです。本当に悪いのは、文字列と整数のフォーマットを混在させた場合です - 文字列は (奇妙なかもしれませんが) 数値としてうまく出力されますが、文字列として渡された場合、数値が「機能する」可能性は低いです - 文字列は最初のアドレスへのポインタであるため文字 - ほとんどの数値は、一般的なシステムでは有効なポインターではないため、クラッシュします。

しかし、何の保証もありません。64 ビットの例では、数値が「リトル エンディアン」であることは明らかです。0x100000000 で同じことを試すと、残りの数値が失われるため、0 が出力されます。

于 2013-01-24T14:57:41.800 に答える
2

はい、printf はフォーマット文字列に依存して、次にフェッチする変数のサイズとタイプを決定します。フォーマット文字列が間違っていると、そこにさえない変数を取得しようとする可能性があり、すべての結果が生じる可能性があります。

于 2013-01-24T14:55:34.690 に答える
-2

printf を使用しないでください

printfは C 時代の遺物であり、もはや必要ありません...std::cout代わりに I/O マニピュレータを使用してください。

于 2013-01-24T15:05:52.713 に答える