apue中memstr.c的究极困惑解决

17 篇文章 0 订阅

这两天因为fmemopen这个函数导致自己一直很迷惑为什么memstr.c中最后一个输出就是不加null字节.

在自己

  • 查看http://man7.org/linux/man-pages/man3/fmemopen.3.html的文档
  • 查看apue英文版
  • 以及苦思冥想了大概4小时之后
    终于找到了网上有个前辈对这里的思考

Third, a null byte is written at the current position in the stream whenever we
increase the amount of data in the stream’s buffer and call fclose, fflush, fseek,fseeko, or fsetpos

中间是and 所以要同时满足这两个条件才会增加一个null字节。因为最后我们的内存流中其实是还有24个字节的,只是把当前位置移动到了开头的位置,所以其实不满足前面的数据量增加 ,所以最后一段代码并不会增加一个null字节。

下面可以看我的代码运行一下memstr.c

// 2020年02月26日22:31:54   52行处还是不懂,卡了40分钟,自闭
// 2020年02月27日18:06:23  自闭4个多小时终于理解了,因为5.7的那个源码题
#include "apue.h"

#define BSZ 48

int
main()
{
    FILE *fp;
    char buf[BSZ];
    char data[62];

    memset(buf, 'a', BSZ-2);
    buf[BSZ-2] = '\0';
    buf[BSZ-1] = 'X';
    // 通过w+读写申请内存流,那么就一开始截断文件(这里是buf)从0开始
    if ((fp = fmemopen(buf, BSZ, "w+")) == NULL)
        err_sys("fmemopen failed");
    printf("initial buffer contents: %s\n", buf);
    fprintf(fp, "hello, world");
    printf("before flush: %s\n", buf);
    fflush(fp);
    printf("after fflush: %s\n", buf);
    // 这里导致偏移量到了12
    printf("len of string in buf = %ld\n", (long)strlen(buf));

    memset(buf, 'b', BSZ-2);
    buf[BSZ-2] = '\0';
    buf[BSZ-1] = 'X';

    printf("initial buffer contents: %s\n", buf);

    fprintf(fp, "hello, world");

    printf("hello world buffer contents: %s\n", buf);

    // fseek让缓冲区刷新,然后就是从12的位置向后添加hello, world\0,然后再fseek到文件开始部分
    // To set file pointer to the beginning of the file
    fseek(fp, 0, SEEK_SET); // We can use rewind(fp); also

    printf("after  fseek: %s\n", buf);
    printf("buffer[26] is still b: %c\n", buf[26]);
    printf("len of string in buf = %ld\n", (long)strlen(buf));

    // 可以通过这样读取出,虽然seek的当前位置变成了开头的地方,但是数量量其实还是有24个Bytes
    fgets ( data, 60, fp );
    printf("\nwhen SEEK_POS = 0.fmemopen data is %s\n And fmemopen still has %d bytes\n\n", data,strlen(data));

    // 我的读取操作完还变动seek位置,所以我们操作完再搞回去
    fseek(fp, 0, SEEK_SET);

    memset(buf, 'c', BSZ-2);
    buf[BSZ-2] = '\0';
    buf[BSZ-1] = 'X';
    fprintf(fp, "hello, world");
    // fclose刷新流,然后就是在文件开始部分写入hello, world,但是竟然没有null截断??????

    /*
    Third, a null byte is written at the current position in the stream whenever we
    increase the amount of data in the stream’s buffer <font color=red>**and**</font> call fclose,
     fflush, fseek,fseeko, or fsetpos

   中间是<font color=red>**and**</font> 所以要同时满足这两个条件才会增加一个null字节。
    <font color=red>**因为最后我们的内存流中其实是还有24个字节的,只是把当前位置移动到了开头的位置,
    所以其实不满足前面的数据量增加**</font> ,所以最后一段代码并不会增加一个null字节。
    */
    fclose(fp);
    printf("after fclose: %s\n", buf);
    printf("len of string in buf = %ld\n", (long)strlen(buf));

    return(0);
}

initial buffer contents: 
before flush: 
after fflush: hello, world
len of string in buf = 12
initial buffer contents: bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
hello world buffer contents: bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
after  fseek: bbbbbbbbbbbbhello, world
buffer[26] is still b: b
len of string in buf = 24

when SEEK_POS = 0.fmemopen data is bbbbbbbbbbbbhello, world
 And fmemopen still has 24 bytes

after fclose: hello, worldcccccccccccccccccccccccccccccccccc
len of string in buf = 46


感谢前辈: https://www.cnblogs.com/ittinybird/p/4483329.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值