printf のすべての機能を発見しようとしていますが、これを試しました:
printf("Test:%+*0d", 10, 20);
印刷する
テスト:%+100d
最初にフラグを使用し+
、次に幅*
とフラグを再利用しました0
。
なぜこの出力を作るのですか?わざと悪いprintf()
意味で使ったのになんで100と表示されるのかな?
printf のすべての機能を発見しようとしていますが、これを試しました:
printf("Test:%+*0d", 10, 20);
印刷する
テスト:%+100d
最初にフラグを使用し+
、次に幅*
とフラグを再利用しました0
。
なぜこの出力を作るのですか?わざと悪いprintf()
意味で使ったのになんで100と表示されるのかな?
これは、コンパイラに構文上のナンセンスを提供しているため、必要なことを自由に行うことができるためです。関連する読み取り、未定義の動作。
警告を有効にしてコードをコンパイルすると、次のようなメッセージが表示されます
警告: 形式 [-Wformat=] に不明な変換タイプの文字 '0' があります
printf("Test:%+*0d", 10, 20);
^
正確には、ステートメントは次のいずれかである必要があります。
printf("Test:%+*.0d", 10, 20); // note the '.'
ここで、は精度0
として使用されます
関連、C11
章 §7.21.6.1 を引用 (強調鉱山)
、、、、、および変換で表示される最小桁数、 、、、、および変換で小数点文字の後に表示される桁数、および変換で表示さ
d
れる有効桁数の最大値を指定するオプションの精度。and変換、または s 変換で書き込まれる最大バイト数。精度は、ピリオド ( ) の後にアスタリスク(後述) またはオプションの 10 進整数が続く形式を取ります。i
o
u
x
X
a
A
e
E
f
F
g
G
.
*
期間のみが指定されている場合、精度はゼロと見なされます。精度が他の変換指定子と共に表示される場合、動作は未定義です。
printf("Test:%+0*d", 10, 20);
ここで、はフラグ0
として使用されます。構文に従って、すべてのフラグは一緒に表示される必要があります。他の変換仕様エントリの前に、変換仕様のどこかにフラグを置いて、コンパイラが意図に従うことを期待することはできません。
繰り返しますが、引用します(そして私の強調)
各変換仕様は、文字によって導入されます
%
。の後に%
、以下が順番に表示されます。
- 0 個以上のフラグ(任意の順序で) [...]
- オプションの最小フィールド幅[...]
- オプションの精度[...]
- オプションの長さ修飾子[...]
- 変換指定子[.... ]
フォーマットが正しくありませprintf
ん: フラグは幅指定子の前に置く必要があります。
*
幅指定子として処理された後、長さ修飾子または変換指定子のprintf
いずれかが必要であり、これらのいずれでもない場合、動作は未定義です。.
0
あなたのライブラリの実装はprintf
奇妙な*
ことをします。それを実際の幅引数に置き換えることで処理しているようです...実装の副作用です。他の人は、プログラムを中止するなど、何か他のことをするかもしれません。このような形式エラーは、変換が続く場合に特に危険です%s
。
コードを次のように変更printf("Test:%+0*d", 10, 20);
すると、期待される出力が生成されます。
Test:+000000020