c - 解析二进制数据时使用属性打包的结构

标签 c memory struct

看过各种代码,其中将数据读入 charvoid 然后 将其转换为 struct。示例是解析数据具有​​固定偏移量的文件格式。

例子:

struct some_format {
    char magic[4];
    uint32_t len;
    uint16_t foo;
};

struct some_format *sf = (struct some_format*) buf;

要确保这始终有效,需要使用 __attribute__((packed)) 对齐 struct

struct test {
    uint8_t a;
    uint8_t b;
    uint32_t c;
    uint8_t d[128];
} __attribute__((packed));

当读取大而复杂的文件格式时,这肯定会使事情变得更加简单。通常 使用具有 30 多个成员等的 structs 读取媒体格式。

它也很容易在巨大的缓冲区中读取并转换为正确的类型,例如:

struct mother {
    uint8_t a;
    uint8_t b;
    uint32_t offset_child;
};

struct child {
     ...
}

m = (struct mother*) buf;
c = (struct child*) ((uint8_t*)buf + mother->offset_child);

或者:

read_big_buf(buf, 4096);

a = (struct a*) buf;
b = (struct b*) (buf + sizeof(struct a));
c = (struct c*) (buf + SOME_DEF);
...

将这样的结构快速写入文件也很容易。


我的问题是这种编码方式的好坏。我在看各种数据 结构,并会使用最好的方法来处理这个问题。

  • 这是如何完成的吗? (如:这是常见的做法。)
  • __attribute__((packed)) 总是安全的吗?
  • 使用 sscanf 是否更好。 我在想什么?,谢谢 @Amardeep
  • 在通过强制转换和位移位启动结构的地方创建函数是否更好。
  • 等等

到目前为止,我主要在数据信息工具中使用它。喜欢列出的所有结构 某种类型,其值采用文件格式,例如媒体流。 信息转储工具。

最佳答案

有时就是这样。只要正确使用,Packed 是安全的。使用 sscanf() 意味着您正在读取文本数据,这与结构中的二进制图像不同。

如果您的代码不需要跨编译器和/或平台(CPU 架构)的可移植性,并且您的编译器支持打包结构,那么这是访问序列化数据的完全合法的方式。

但是,如果您尝试在一个平台上生成数据并在另一个平台上使用它,则可能会出现问题,原因是:

  1. 主机字节顺序(小端/大端)
  2. 语言原始类型的不同大小(例如 long 可以是 32 位或 64 位)
  3. 一侧的代码发生变化,另一侧没有。

有些库可以简化序列化/反序列化并处理其中的大部分问题。在必须跨越进程和主机的系统上,此类操作的开销更容易证明是合理的。但是,如果您的结构非常复杂,使用 ser/des 库可能仅仅是因为易于维护。

关于c - 解析二进制数据时使用属性打包的结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16405250/

相关文章:

c - 内核 : using sigqueue-functions

c# - 您可以使用 List<List<struct>> 绕过 2gb 对象限制吗?

c++ - 具有 3 字节 block 的序列化 C++ 结构?

java - 如何使用 log4j 在配置文件中配置 Appender 类

c++ - GCC/CLANG 预处理器与 MSVC 之间的差异是什么?

c++ - ncurses:移动/调整窗口大小后 wgetch 无法正确读取

c - LPC1788微 Controller 的原子测试和设置

C malloc 函数的大小参数

c - 为什么当大小大于 8192 字节时 realloc() 不起作用?

在链表中使用指向结构的指针时出现 C 段错误