あいまいさはC標準自体から始まります。C99とC11はどちらもsnprintf
機能の説明が同じです。これがC99からの説明です:
7.19.6.5snprintf
関数
概要
1 #include <stdio.h>
int snprintf(char * restrict s, size_t n, const char * restrict format, ...);
説明
2このsnprintf
関数はfprintf
、出力がs
ストリームではなく配列(引数で指定)に書き込まれることを除いて、と同等です。Ifはn
ゼロであり、何も書かれていない、とs
NULLポインタかもしれません。それ以外の場合、n-1
stを超える出力文字は配列に書き込まれるのではなく破棄され、実際に配列に書き込まれた文字の最後にヌル文字が書き込まれます。オーバーラップするオブジェクト間でコピーが行われる場合、動作は定義されていません。
戻り値
3このsnprintf
関数は、書き込まれたはずの文字数を返します。n
十分に大きく、終了ヌル文字をカウントしないか、エンコードエラーが発生した場合は負の値。したがって、戻り値が負でなく、n
。未満である場合にのみ、ヌル終了出力が完全に書き込まれます。
一方では、文
それ以外の場合、stを超える出力文字n-1
は配列に書き込まれるのではなく破棄され、実際に配列に書き込まれた文字の最後にヌル文字が書き込まれます。
(s
3文字の長さの配列を指し、)n
が3の場合、2文字が書き込まれ、2文字を超える文字は破棄されると言います。次に、それらの2の後にヌル文字が書き込まれます(ヌル文字は3番目に書き込まれる文字になります)。
そして、これは元の質問に答えると私は信じています。
答え:
重複するオブジェクト間でコピーが行われる場合、動作は定義されていません。が0の
場合n
、出力には何も書き込まれ
ません。エンコードエラーが発生しなかった場合、出力は常にnullで終了します(出力が出力配列に収まるかどうかに関係なく、そうでない場合、一部の文字は破棄され、出力が配列がオーバーフローすることはありません)、
そうでない場合(エンコードエラーが発生した場合)、出力はnullで終了しないままになる可能性があります。
一方
、最後の文
したがって、戻り値が負でなく、以下の場合にのみ、ヌル終了出力が完全に書き込まれます。 n
あいまいさを与えます(または私の英語は十分ではありません)。私は、少なくとも2つの方法でこの文を解釈することができます:
1.出力されている、NULLで終了する場合は、返された値が非負とされている場合にのみ未満n
返された値がされた場合にどの手段(ない未満n
、すなわち出力(含みますnull文字を終了する)が配列に収まらない場合、出力はnullで終了しません)。
2.戻り値が負でなく、。未満の場合にのみ、出力は完了します(文字は破棄されていません)。n
上記の解釈1は答えと矛盾し、誤解と長い議論を引き起こすと私は信じています。そのため、snprintf
関数を説明する最後の文は、あいまいさを取り除くために変更が必要です(これにより、C言語標準への提案を作成する根拠が得られます)。リンクの@ "Martin Ba"のおかげで、
あいまいでない表現の例はhttp://en.cppreference.com/w/c/io/fprintf(を参照4)
)から取得できます。
「snprintf:この関数の説明を変更するためのC標準の提案/計画はありますか?」という質問も参照してください。