c - 将原始结构内容(字节)写入 C 中的文件。对写入的实际大小感到困惑

标签 c struct sizeof fwrite

基本问题,但我希望这个结构占用 13 个字节的空间(1 个用于 char,12 个用于 3 个无符号整数)。相反,sizeof(ESPR_REL_HEADER) 给我 16 个字节。

typedef struct {
  unsigned char version;
  unsigned int  root_node_num;
  unsigned int  node_size;
  unsigned int  node_count;
} ESPR_REL_HEADER;

我想做的是用一些值初始化这个结构并将它包含的数据(原始字节)写入文件的开头,这样当我打开这个文件时我可以稍后重建这个结构和获取有关文件其余部分包含内容的一些元数据。

我正在初始化结构并将其写入文件,如下所示:

int esprime_write_btree_header(FILE * fp, unsigned int node_size) {
  ESPR_REL_HEADER header = {
    .version       = 1,
    .root_node_num = 0,
    .node_size     = node_size,
    .node_count    = 1
  };

  return fwrite(&header, sizeof(ESPR_REL_HEADER), 1, fp);
}

在我进行实验时,node_size 当前为 4。

在我向其写入结构后,该文件包含以下数据:

-bash$  hexdump test.dat
0000000 01 bf f9 8b 00 00 00 00 04 00 00 00 01 00 00 00
0000010

我希望它实际包含:

-bash$  hexdump test.dat
0000000 01 00 00 00 00 04 00 00 00 01 00 00 00
0000010

请原谅新手。我正在努力学习 :) 如何高效地将结构的数据组件写入文件?

最佳答案

微处理器不是为从任意地址获取数据而设计的。诸如 4 字节 int 之类的对象应该只存储在可被 4 整除的地址。此要求称为 alignment .

C 允许编译器自由插入 padding bytes在结构成员之间对齐它们。填充量只是不同平台之间的一个变量,另一个主要变量是endianness。 .这就是为什么如果您希望程序在多台机器上运行,您不应该简单地将结构“转储”到磁盘。

最佳实践是显式地编写每个成员,并使用 htonl在二进制输出之前将字节顺序固定为大端。回读时,使用memcpy移动原始字节,不要使用

char *buffer_ptr;
...
++ buffer_ptr;
struct.member = * (int *) buffer_ptr; /* potential alignment error */

而是做

memcpy( buffer_ptr, (char *) & struct.member, sizeof struct.member );
struct.member = ntohl( struct.member ); /* if member is 4 bytes */

关于c - 将原始结构内容(字节)写入 C 中的文件。对写入的实际大小感到困惑,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10153155/

相关文章:

c - 如何修改C中结构体中的字符串?

c - 基本数据类型的位数

c++ - 在 C++ 中查找字符串数组的大小

c - 使用位掩码和 if 语句

c++ - 仅从 date int C/C++ 获取日期信息

c++ - 获取内存地址的值

python - 从 Python 创建独立的文本应用程序

c - 复制我的嵌套结构时出了什么问题?

c - 在 C 中重新声明为不同类型的符号错误

c - 如何找到数组的大小(从指向数组第一个元素的指针)?