我正在测试fseek和fgetpos的交互(更确切地说,如果我能得到一个多字节内的fpos_t)并且进入一个非常意外的情况。
每当我使用setlocale(LC_CTYPE, "C.UTF-8");
和fputwc
时,fseek
似乎不再起作用,将光标移动到文件中的唯一方法是使用fgetwc
。
代码如下(所有调用成功完成,即setlocale,fseek,fputwc等等。为简洁起见,我删除了返回值的检查)。
这在Ubuntu上发生了glibc 2.16。有没有人有一个很好的解释为什么会这样?这是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
一些注意事项:
如果我关闭文件并在阅读中重新打开它,那么一切都按预期工作(fseek
后,ftell_out
/ fpos_out
为1
和{{由于位置在多字节内,因此1}}失败并显示正确的fgetwc
如果我不使用errno
,则输出几乎与预期一致,只是setlocale
不再设置fgetwc
。