我正在阅读APUE
并在stdio.h中尝试内存流。但是,我对自动编写\0
的机制感到非常困惑。
以下是APUE
5.14 Memory Streams
上所说的内容:
每当我们增加流缓冲区中的数据量并调用fclose,fflush,fseek,fseeko或fsetpos
时,就会在流中的当前位置写入空字节
我使用以下代码进行了一些实验,以测试Increase the amount of data in the stream's buffer
:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define BSZ 48
int main(){
FILE *fp;
char buf[BSZ];
memset(buf, 'a', BSZ-2);
buf[BSZ-2] = '\0';
buf[BSZ-1] = 'X';
printf("Initial buffer content: %s\n", buf);
if ((fp = fmemopen(buf, BSZ, "w+")) == NULL){
fputs("fmemopen failed\n", stderr);
exit(-1);
}
fprintf(fp, "hello, world");
/* Confused Point Here !!! */
fflush(fp); //works as expected
//fseek(fp, 12, SEEK_SET); //strange behavior
printf("after fflush/fseek: %s\n", buf);
fprintf(fp, "hello, world2");
fclose(fp);
printf("after fclose: %s\n", buf);
exit(0);
}
在flush()
的第一个输出后,fseek()
和'\0'
都会自动写入"hello, world"
。
在'hello,world'的第二个输出之后,行为是不同的,并调用fclose():
当我使用flush()
时,"hello, world"
的第二个输出后跟'\0'
,这是我的预期:
初始缓冲内容:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 在fflush / fseek之后:你好,世界
在fclose之后:你好,worldhello,world2
但是,当我切换到fseek(fp, 12, SEEK_SET)
时,"hello, world"
的第二个输出后面不再是'\ 0':
初始缓冲内容:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 在fflush / fseek之后:你好,世界
fclose之后:hello,worldhello,world2aaaaaaaaaaaaaaaaaaaaa
这意味着内存流不会将第二个输出视为increasing the amount of data
。
我在SUSE Linux Enterprise Server 11(x86_64)SP1上进行了此实验
你有什么想法吗?或者它实际上是系统的错误?
非常感谢。
答案 0 :(得分:0)
[评论太长了:]
每当我们增加流缓冲区中的数据量并调用fclose,fflush,fseek,fseeko或fsetpos
时,就会在流中的当前位置写入空字节
文档与 APUE 的上述引用不同:
刷新已打开以进行写入的流时(fflush(3)) 或者关闭(fclose(3)),在结尾处写入一个空字节 缓冲区,如果有空间。 [...]可以使用fseek(3)或fseeko(3)更改流的文件位置。将文件位置移动到已经写入的数据的末尾,用零填充中间空间。
当一个打开写入的流被刷新或关闭时,应在当前位置或缓冲区末尾写入一个空字节,具体取决于内容的大小。
因此,POSIX并不像Linux文档那样具有解释性,而是在fseek*
上重新做什么。