2

我正在测试 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 重新打开它,那么一切都按预期工作(之后fseekftell_out/ fpos_outare1并且fgetwc失败,errno因为位置在多字节内)

  • 如果我不使用setlocale输出几乎如预期的那样,除了fgetwc不再设置errno

4

0 回答 0