我正在测试 fseek 和 fgetpos 的交互(更准确地说,如果我能得到一个多字节内的 fpos_t )并进入了一个非常意想不到的情况。
每当我使用setlocale(LC_CTYPE, "C.UTF-8");
andfputwc
时, 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
are1
并且fgetwc
失败,errno
因为位置在多字节内)如果我不使用
setlocale
输出几乎如预期的那样,除了fgetwc
不再设置errno
。