C ';正确的';在内存流上使用ftell()时的语义

C ';正确的';在内存流上使用ftell()时的语义,c,posix,stdio,ftell,C,Posix,Stdio,Ftell,有人能解释ftell()在内存流上使用时的“正确”语义吗 鉴于以下计划: #include <stdio.h> #include <stdlib.h> #include <gnu/libc-version.h> int main(void) { puts (gnu_get_libc_version ()); size_t n_buffer = 1024; char *buffer = calloc(n_buffer, sizeof(cha

有人能解释ftell()在内存流上使用时的“正确”语义吗

鉴于以下计划:

#include <stdio.h>
#include <stdlib.h>
#include <gnu/libc-version.h>

int main(void)
{
   puts (gnu_get_libc_version ());

   size_t n_buffer = 1024;
   char *buffer = calloc(n_buffer, sizeof(char));
   FILE *file = fmemopen(buffer, n_buffer, "w");

   /* "ABCD" */
   static const char magic_number[] = 
   {
     0x41, 0x42, 0x43, 0x44 
   };

   const size_t written = fwrite(magic_number, 1, 4, file);
   fprintf(stderr,"written=%d\n",written);

   int fstatus = fflush(file);
   fprintf(stderr,"fstatus=%d\n",fstatus);

   long ftellpos = ftell(file);
   fprintf(stderr,"ftellpos=%ld\n",ftellpos);

   fstatus = fseek(file, 0, SEEK_END);
   fprintf(stderr,"fstatus=%d\n",fstatus);

   ftellpos = ftell(file);
   fprintf(stderr,"ftellpos2=%ld\n",ftellpos);

   return 0;
}
而OpenSUSE Leap 42的输出为:

2.22
written=4
fstatus=0
ftellpos=0
fstatus=0
ftellpos2=4
(这导致了我所看到的代码中的单元测试失败)

我的问题是:

  • 标准是否需要fseek()使ftell()的结果有效
  • 这是glibc行为中的错误还是变化
  • 为什么它在OpenSUSE上不起作用
最明显的实现是使用文件位置指示器 内存缓冲区中提供给fmemopen的索引。 很难看出这怎么会出错

实际上,执行:

有c->pos=pos+s;在第85行

大概ftell()只返回c->pos(以一种迂回的方式)

在2.17和2.22之间,对glibc源进行了一些重组 如果我能解开它,这也许能解释这一点。 但这是一个bug还是一个特性

我不确定Posix和C标准是否完全规定了ftell 对于内存流,应该可以正常工作。 凭直觉很难理解为什么它不应该被强制执行 应该只是工作

说:

“当前位置由I/O操作隐式更新。 它可以使用fseek(3)显式更新,并使用ftell(3)确定。”

其他手册页提到ftell可能不必工作 对于不是真正的文件的东西。
然而,我相信他们在那里真的有设备。

刚刚在网上的一次讨论中发现了这句话:

ftell()Open Group Base Specifications Issue 7文档说明“ftell()应返回流的文件位置指示器的当前值”。如果没有对fflush函数或文件定位函数(fseek、fsetpos或rewind)的中间调用,或直到缓冲区满,文件位置指示器不会更新


因此,在rh和suse中似乎存在一些缓冲区处理差异。您需要以某种方式刷新缓冲区以读取文件中的正确位置

那么,关于标准函数的唯一权威资源告诉了你什么呢?听起来像是一个bug——虽然不太可能是这个问题,但这里所做的随意的整数类型转换给文章增加了不必要的问题。建议使用正确的类型和打印说明符
ftell()
返回
long
size\u t
需要一个
“zu”
@Olaf有两个授权源C和Posix。我相信两者都没有定义,但我不是语言律师。因此我的问题。@o11c我相信你是对的。它要么是实现中的缺陷(我相信),要么是文档中的缺陷,或者两者兼而有之。我已经在这里提交了一份bug报告:让我们看看维护人员有什么要说的。我很清楚这个需求。请注意,在我最初的示例中,在编写之后有一个对fflush的调用。“我在泥中的某个地方发现了这个”并不是一个好的开始。这不能回答是否允许这样做(它是)。@Olaf是的,我知道,但它指向一个文档并解释了行为。我没有看到任何“指针”,它也是错误的/误导的。阅读标准,而不是晦涩难懂的论坛@Olaf欢迎您提供标准的报价。请注意。
2.22
written=4
fstatus=0
ftellpos=0
fstatus=0
ftellpos2=4