技术解析

问一个 C 语言关于文件操作的问题,如何将 uint32_t 数据写进二进制文件, 4byte 对齐?
0
2021-06-16 16:54:14
idczone
fwrite 的第一个参数是 char 类型,好像不支持啊?应该用什么方法写入。
在不考虑字节序的情况下,盲猜每次读 8bit 再写入?

1. open 的时候加参数 binary
2. 写对齐没有意义

第一个不是 char 类型,而是指向 buffer 的一个指针;第二个参数是 buffer 的长度,因此要达到写 4 bytes (sizeof(uint32_t))的效果,你需要 ( https://godbolt.org/z/zMMWb3 ):
```c


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

需要先把 uint32_t 转化成 4 个 char,这里涉及大小端的问题,可以搜一下「大小端」

对齐与否之前只有在内存中才有必要对齐,更何况现在不对齐的内存访问也已经很快了,你没有必要对齐

对齐感觉没用

不知道 C 怎么做,C++内置了关键字 直接 alignas(4) uint_32 即可

C 语言层次,我不建议你去主动对齐,因为这个层次的文件读写,本质是把 buffer 交给 OS 去处理的,最后这些 buffer data 写到存储设备时,是否进行对齐 io,是由 OS 来决定的。
OS 在把数据 flush 到存储设备上的优化动作,可不止对齐一种。

我记得只有在 malloc 的时候对齐吧

(char*)&num 直接转成 char 类型数组写入 4 个字节就行。本身 uint32_t 就是 4 个字节也不用考虑对齐问题吧。读的时候四个四个读把 char 数组转回 uint32_t 也不用考虑字节序的问题了

uint32_t 不就是 4 个字节,还对齐什么

mmap 要写入的文件,然后 align 要写入的地址,然后 memcpy.
类似这样:
fd = open()
addr = mmap()
ptr = addr + offset
ptr = align()
memcpy(ptr, &int_var, sizeof(int))

要考虑大端还是小端储存

以 binary 形式打开文件,写多少个字节就是多少个字节

看#3,怎么写进去将来用的时候怎么读出来就行了。

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 上的

我感觉直接写就是对齐的,为此我还特意写代码测试了一下:

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...........

你写到文件是几字节对齐应该是与你的数据在内存中是几字节对齐一致的,毕竟写的时候只是把内存原样写进去。
如果你设置了内存 1 字节对齐,那么写到文件也是 1 字节对齐的。


struct 里面的 field 都会 self-align,把 int b 放到 char a 前面,char c 就不会 align 到 4 bytes 上了。

感谢大佬,不过我有个疑问,假设我的数据类型是 uint32_t,但是我 fwrite 的时候大小填写的 5 或者 8 (不为 uint32_t 的 4 ),我写进去的数据是真实的吗?多余的字节数会产生什么异变吗?

理解了。

数据地带为您的网站提供全球顶级IDC资源
在线咨询
专属客服