如何在没有填充位的情况下在C中输出二进制文件

Joa*_*ira 3 c binary bits padding output

我想将结构数据输出到二进制文件,但每个变量的信息之间没有任何填充位.例如:

struct s {
    int i1;
    short s1;
    char c1;
};
struct s example[2];
Run Code Online (Sandbox Code Playgroud)

如果我使用fwrite(&example, sizeof(struct s), 2, file)的二进制文件仍然之间,例如,填充比特s1c1,也从c1i1 (of the 2nd struct).

从输出文件中删除这些填充位的好方法是什么?

谢谢!任何帮助表示赞赏

Dra*_*rgy 5

我建议单独手动读取/写入结构的成员.使用编译器指令进行打包可能会导致未对齐数据访问的低效率和可移植性问题.如果你必须处理字节序,那么稍后当你的读操作分解为字段成员而不是整个结构时,很容易支持.

另一件事,这与未来的维护类型问题有关,就是你不希望你的序列化代码或人们迄今为止保存的文件中断,如果你稍微改变一下结构(添加新元素甚至改变顺序)作为高速缓存行优化,例如).因此,与使用直接将结构的内存内容直接转储到文件中提供更多喘息空间的代码相比,您可能会遇到更少的痛苦,而且通常最终值得单独序列化您的成员.

如果要概括模式并减少所编写的样板量,可以执行以下操作作为启动和构建的基本示例:

struct Fields
{
     int num;
     void* ptrs[max_fields];
     int sizes[max_fields];
};

void field_push(struct Fields* fields, void* ptr, int size)
{
    assert(fields->num < max_fields);
    fields->ptrs[fields->num] = ptr;
    fields->sizes[fields->num] = size;
    ++fields->num;
}

struct Fields s_fields(struct s* inst)
{
    struct Fields new_fields;
    new_fields.num = 0;

    field_push(&new_fields, &inst->i1, sizeof inst->i1);
    field_push(&new_fields, &inst->s1, sizeof inst->s1);
    field_push(&new_fields, &inst->c1, sizeof inst->c1);

    return new_fields;
}
Run Code Online (Sandbox Code Playgroud)

现在,您可以将此Fields结构与通用函数一起使用来读取和写入任何结构的成员,如下所示:

void write_fields(FILE* file, struct Fields* fields)
{
    int j=0;
    for (; j < fields->num; ++j)
         fwrite(fields->ptrs[j], fields->sizes[j], 1, file);
}
Run Code Online (Sandbox Code Playgroud)

for_each_field接受回调的某种功能方法相比,这通常更容易使用.

现在,您只需要在创建一个新结构时担心S,就是定义一个函数struct Fields从实例输出,然后启用您编写的所有常用函数,struct Fields以便现在S自动使用这个新类型.