yohhoyの日記

技術的メモをしていきたい日記

標準入出力とchar/wchar_t型の混在

C/C++標準ライブラリの標準入出力ストリームにおける charwchar_t 型混在についてメモ。またはCの printfwprintf 関数、C++coutwcout オブジェクト混在利用に関する話題。

まとめ:ある標準入出力ストリームに対する charwchar_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 the fwide function can otherwise alter the orientation of a stream. (A successful call to freopen 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 streams stdin, stdout, and stderr 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標準ライブラリに従う*1C++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,wcincout, wcoutcerr, wcerr は、それぞれ stdinstdoutstderr に関連付けられたストリームバッファを制御する(C++03 27.3.1, 27.3.2)。

関連URL

*1:前述のC99標準規格はC++標準規格が参照する"Amendment 1 of the ISO C standard"を包含する(JTC1/SC22/WG14 N1256 Foreword/p5)

*2:C++11(JTC1/SC22/WG21 N3337)では27.4.1/p3