C/C++標準ライブラリの標準入出力ストリームにおける char/wchar_t 型混在についてメモ。またはCの printf/wprintf 関数、C++の cout/wcout オブジェクト混在利用に関する話題。
まとめ:ある標準入出力ストリームに対する char/wchar_t 入出力操作の混在禁止。
C言語
C標準ライブラリ提供の(ファイル)ストリームは、「orientation未確定」「バイト指向ストリーム(byte-oriented stream)」「ワイド指向ストリーム(wide-oriented stream)」のいずれかの状態をとる。プログラム初期化直後の標準入出力ストリームはorientationを持たないが、最初に入出力操作を行った関数に応じてバイト指向/ワイド指向が決まる。例:printf関数 → バイト指向、wprintf関数 → ワイド指向。
バイト指向ストリームに対してワイド文字入出力操作、またはその逆を行った場合は未定義動作(undefined behavior)となる。ストリームのorientationが一度決定されると、そのストリームが閉じられるまでorientationは固定される。なお、fwide関数は一度決定されたorientationを変更しない(N1256 7.24.3.5/p2の脚注)。
C99(JTC1/SC22/WG14 N1256) 7.19.2/p4-5, J.2より一部引用。
4 Each stream has an orientation. After a stream is associated with an external file, but before any operations are performed on it, the stream is without orientation. Once a wide character input/output function has been applied to a stream without orientation, the stream becomes a wide-oriented stream. Similarly, once a byte input/output function has been applied to a stream without orientation, the stream becomes a byte-oriented stream. Only a call to the
freopenfunction or thefwidefunction can otherwise alter the orientation of a stream. (A successful call tofreopenremoves any orientation.)233)
5 Byte input/output functions shall not be applied to a wide-oriented stream and wide character input/output functions shall not be applied to a byte-oriented stream. (snip)
脚注233:The three predefined streamsstdin,stdout, andstderrare unoriented at program startup.
J.2 Undefined behavior
- A byte input/output function is applied to a wide-oriented stream, or a wide character input/output function is applied to a byte-oriented stream (7.19.2).
C++言語
C++標準ライブラリ提供のスリームオブジェクトに関して、narrow文字(char)/wide文字(wchar_t)ストリーム混在操作のセマンティクスはC標準ライブラリに従う*1。C++03 27.3/p2より一部引用*2。
2 Mixing operations on corresponding wide- and narrow-character streams follows the same semantics as mixing such operations on
FILEs, as specified in Amendment 1 of the ISO C standard. (snip)
標準入出力ストリームオブジェクト cin,wcin/cout, wcout/cerr, wcerr は、それぞれ stdin/stdout/stderr に関連付けられたストリームバッファを制御する(C++03 27.3.1, 27.3.2)。
関連URL