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
freopen
function or thefwide
function can otherwise alter the orientation of a stream. (A successful call tofreopen
removes 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
, andstderr
are 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
FILE
s, 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