看过各种代码,其中将数据读入 char
或 void
然后
将其转换为 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))
总是安全的吗?使用我在想什么?,谢谢 @Amardeepsscanf
是否更好。- 在通过强制转换和位移位启动结构的地方创建函数是否更好。
- 等等
到目前为止,我主要在数据信息工具中使用它。喜欢列出的所有结构 某种类型,其值采用文件格式,例如媒体流。 信息转储工具。
最佳答案
有时就是这样。只要正确使用,Packed 是安全的。使用 sscanf() 意味着您正在读取文本数据,这与结构中的二进制图像不同。
如果您的代码不需要跨编译器和/或平台(CPU 架构)的可移植性,并且您的编译器支持打包结构,那么这是访问序列化数据的完全合法的方式。
但是,如果您尝试在一个平台上生成数据并在另一个平台上使用它,则可能会出现问题,原因是:
- 主机字节顺序(小端/大端)
- 语言原始类型的不同大小(例如 long 可以是 32 位或 64 位)
- 一侧的代码发生变化,另一侧没有。
有些库可以简化序列化/反序列化并处理其中的大部分问题。在必须跨越进程和主机的系统上,此类操作的开销更容易证明是合理的。但是,如果您的结构非常复杂,使用 ser/des 库可能仅仅是因为易于维护。
关于c - 解析二进制数据时使用属性打包的结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16405250/