fseek と fgetpos の相互作用をテストしていたところ (より正確には、マルチバイト内にある fpos_t を取得できるかどうか)、かなり予期しない状況に陥りました。
setlocale(LC_CTYPE, "C.UTF-8");
andを使用するたびにfputwc
、 fseek
もう機能しないようで、ファイル内でカーソルを移動する唯一の方法は を使用することfgetwc
です。
コードは次のとおりです (すべての呼び出しは正常に完了します。つまり、setlocale、fseek、fputwc などです。簡潔にするために、戻り値のチェックを取り除きました)。
これは、glibc 2.16 を使用する Ubuntu で発生します。なぜこれが起こるのか、誰かが良い説明を持っていますか? これは glibc のバグですか?
setlocale(LC_CTYPE, "C.UTF-8");
uselocale(LC_GLOBAL_LOCALE);
FILE* fp = fopen("/tmp/wc.test", "w+");
wchar_t wc = 0x00a2;
fputwc(wc, fp);
fflush(fp);
rewind(fp);
long ftell_out;
fpos_t fpos_out;
fseek(fp, 1, SEEK_SET); // looks like it doesn't have any effect
ftell_out = ftell(fp); // ftell_out is 0
fgetpos(fp, &fpos_out); // the (inner) offset of fpos_out is 0 as well
fgetwc(fp); // it reads wc(0x00a2) here as if we are at
ftell_out = ftell(fp); // this is 2
fgetpos(fp, &fpos_out); // this is 2
いくつかのメモ:
ファイルを閉じて read more で再度開くと、すべてが期待どおりに機能します (位置がマルチバイト内にあるため
fseek
、ftell_out
/fpos_out
が適切1
でfgetwc
失敗した後)errno
私が使用しない場合
setlocale
、出力はほとんど期待どおりですfgetwc
が、もう設定されていませerrno
ん。