假设我有一个使用POSIX扩展的C程序,有一个FILE *fp和它的文件描述符int fd. 我可以假设fd(按照lseek(fd, 0, SEEK_CUR))的"文件位置"应该与fp(按照ftell(fp))的"文件位置"相匹配吗? "假设"是指"POSIX要求..."

推荐答案

我认为可以肯定地说,你可以假设有一些情况下,他们don't匹配.

一个明显的例子是预读:stdio通常读取一个字节的块,不管应用程序要求多少字节.然后,ftell()将根据应用程序代码读取的量来判断位置,而lseek()将根据从操作系统读取的量来判断位置.

试试这样做:

$ cat > seek.c <<'EOF'
#include <stdio.h>
#include <unistd.h>

char buf[123];
int main(void) {
    int fd = fileno(stdin);
    fread(buf, 12, 3, stdin);
    long pos1 = ftell(stdin);
    long pos2 = lseek(fd, 0, SEEK_CUR);
    printf("ftell: %ld lseek: %ld\n", pos1, pos2);
    return 0;
}
EOF
$ gcc -Wall -o seek seek.c
$ ./seek < dummyfile
ftell: 36 lseek: 4096

类似地,由于写缓冲,低级fd位置将落后于stdio文件位置.

正如在 comments 中提到的,standard has instructions on what to do when accessing a single file through multiple handles(fds或stdio流).对于不同的情况,有几个步骤可以采取,但通过我的阅读,它似乎可以归结为:

  1. 确保先前使用的句柄已清除了它保留的所有缓冲区(例如,fflush(),无论它是用于读还是写).
  2. 在下一个要使用的句柄上调用fseek()lseek().

就我个人而言,我会避免陷入这种混乱.

C++相关问答推荐

如何将匿名VLA分配给指针?

Apple Libm的罪恶功能

C如何显示字符串数组中的第一个字母

返回一个包含数组的 struct

*p[num]和(*p)num的区别

为什么在4.9.37版的内核中,kfio还需要smp_wmb呢?

我无法让LLDB正确运行我的可执行文件

getline()从c中的外部函数传递指针时输出null

ifdef __cplusplus中的整数文字单引号

正数之和是负数

使用ld将目标文件链接到C标准库

如何在c中使用具有不同变量类型的内存分配?

为什么编译器不能简单地将数据从EDI转移到EAX?

我不知道为什么它不能正常工作,我用了get()和fget(),结果是一样的

使用C++中的字符串初始化 struct 时,从‘char*’初始化‘char’使指针变为整数,而不进行强制转换

基于蝶数恰好有8个除数的事实的代码

我编写这段代码是为了判断一个数字是质数、阿姆斯特朗还是完全数,但由于某种原因,当我使用大数时,它不会打印出来

x86-64平台上的int_fast8_t大小与int_fast16_t大小

在分配内存后使用指针是未定义的行为吗?

C11 嵌套泛型