C ';正确的';在内存流上使用ftell()时的语义
有人能解释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
#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上不起作用
然而,我相信他们在那里真的有设备。刚刚在网上的一次讨论中发现了这句话: 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