V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Distributions
Ubuntu
Fedora
CentOS
中文资源站
网易开源镜像站
ReputationZh
V2EX  ›  Linux

问一个 C 语言关于文件操作的问题,如何将 uint32_t 数据写进二进制文件, 4byte 对齐?

  •  
  •   ReputationZh · 2020-08-24 23:59:21 +08:00 · 2899 次点击
    这是一个创建于 1580 天前的主题,其中的信息可能已经有所发展或是发生改变。
    fwrite 的第一个参数是 char 类型,好像不支持啊?应该用什么方法写入。
    21 条回复    2020-08-27 09:28:45 +08:00
    dangyuluo
        1
    dangyuluo  
       2020-08-25 00:01:56 +08:00
    在不考虑字节序的情况下,盲猜每次读 8bit 再写入?
    louettagfh
        2
    louettagfh  
       2020-08-25 00:12:15 +08:00
    1. open 的时候加参数 binary
    2. 写对齐没有意义
    zwy100e72
        3
    zwy100e72  
       2020-08-25 00:27:20 +08:00   ❤️ 1
    第一个不是 char 类型,而是指向 buffer 的一个指针;第二个参数是 buffer 的长度,因此要达到写 4 bytes (sizeof(uint32_t))的效果,你需要 ( https://godbolt.org/z/zMMWb3 ):

    ```c
    #include <cstdint>
    #include <cstdio>

    void f(uint32_t i) {
    FILE* fp = fopen("path/to/file.bin", "wb");
    fwrite(&i, sizeof(i), 1, fp);
    fclose(fp);
    }
    ```

    https://en.cppreference.com/w/c/io/fwrite
    XiaoxiaoPu
        4
    XiaoxiaoPu  
       2020-08-25 00:27:54 +08:00
    需要先把 uint32_t 转化成 4 个 char,这里涉及大小端的问题,可以搜一下「大小端」
    zwy100e72
        5
    zwy100e72  
       2020-08-25 00:29:14 +08:00
    对齐与否之前只有在内存中才有必要对齐,更何况现在不对齐的内存访问也已经很快了,你没有必要对齐
    baoshuo
        6
    baoshuo  
       2020-08-25 01:00:02 +08:00
    对齐感觉没用
    Tony042
        7
    Tony042  
       2020-08-25 02:12:13 +08:00
    不知道 C 怎么做,C++内置了关键字 直接 alignas(4) uint_32 即可
    laminux29
        8
    laminux29  
       2020-08-25 03:29:20 +08:00
    C 语言层次,我不建议你去主动对齐,因为这个层次的文件读写,本质是把 buffer 交给 OS 去处理的,最后这些 buffer data 写到存储设备时,是否进行对齐 io,是由 OS 来决定的。

    OS 在把数据 flush 到存储设备上的优化动作,可不止对齐一种。
    yngzij
        9
    yngzij  
       2020-08-25 07:46:39 +08:00 via iPhone
    我记得只有在 malloc 的时候对齐吧
    chinuno
        10
    chinuno  
       2020-08-25 08:37:12 +08:00 via Android
    (char*)&num 直接转成 char 类型数组写入 4 个字节就行。本身 uint32_t 就是 4 个字节也不用考虑对齐问题吧。读的时候四个四个读把 char 数组转回 uint32_t 也不用考虑字节序的问题了
    shuax
        11
    shuax  
       2020-08-25 08:52:29 +08:00
    uint32_t 不就是 4 个字节,还对齐什么
    heguangyu5
        12
    heguangyu5  
       2020-08-25 09:32:36 +08:00
    mmap 要写入的文件,然后 align 要写入的地址,然后 memcpy.

    类似这样:

    fd = open()
    addr = mmap()
    ptr = addr + offset
    ptr = align()
    memcpy(ptr, &int_var, sizeof(int))
    yolee599
        13
    yolee599  
       2020-08-25 09:33:13 +08:00
    要考虑大端还是小端储存
    May725
        14
    May725  
       2020-08-25 12:14:42 +08:00 via iPhone
    以 binary 形式打开文件,写多少个字节就是多少个字节
    Chenamy2017
        15
    Chenamy2017  
       2020-08-25 12:55:45 +08:00
    看#3,怎么写进去将来用的时候怎么读出来就行了。
    CRVV
        16
    CRVV  
       2020-08-25 13:04:14 +08:00
    size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);

    fwrite 的第一个参数明明是 const void* 类型

    直接
    uint32_t x;
    fwrite(&x, 4, ...)
    应该就能用

    另外,没有理解楼主说的 对齐 是指什么,如果从头开始写,每次写 4 bytes,那当然是对齐到 4 bytes 上的
    wizardoz
        17
    wizardoz  
       2020-08-25 13:13:34 +08:00
    我感觉直接写就是对齐的,为此我还特意写代码测试了一下:
    #include <stdio.h>

    typedef struct {
    char a;
    int b;
    char c;
    } Test_t;

    int main(int argc, char* argv[]) {
    Test_t test = {
    .a = 1,
    .b = 2,
    .c = 3
    };

    FILE *fp = fopen("/tmp/data.bin", "wb");
    if (fp != NULL) {
    fwrite(&test, sizeof(test), 1, fp);

    fclose(fp);
    }
    return 0;
    }

    文件内容:
    00000000: 0156 0000 0200 0000 037f 0000 0a .V...........
    wizardoz
        18
    wizardoz  
       2020-08-25 13:16:31 +08:00
    你写到文件是几字节对齐应该是与你的数据在内存中是几字节对齐一致的,毕竟写的时候只是把内存原样写进去。
    如果你设置了内存 1 字节对齐,那么写到文件也是 1 字节对齐的。
    CRVV
        19
    CRVV  
       2020-08-25 13:21:18 +08:00
    @wizardoz

    struct 里面的 field 都会 self-align,把 int b 放到 char a 前面,char c 就不会 align 到 4 bytes 上了。
    ReputationZh
        20
    ReputationZh  
    OP
       2020-08-27 09:26:04 +08:00
    @zwy100e72 感谢大佬,不过我有个疑问,假设我的数据类型是 uint32_t,但是我 fwrite 的时候大小填写的 5 或者 8 (不为 uint32_t 的 4 ),我写进去的数据是真实的吗?多余的字节数会产生什么异变吗?
    ReputationZh
        21
    ReputationZh  
    OP
       2020-08-27 09:28:45 +08:00
    @wizardoz 理解了。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2814 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 20ms · UTC 08:51 · PVG 16:51 · LAX 00:51 · JFK 03:51
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.