【发布时间】:2015-09-11 05:21:51
【问题描述】:
我正在设计一种二进制文件格式来存储字符串[不终止 null 以节省空间]和二进制数据。
我。处理小/大端系统的最佳方法是什么? i.a 将所有内容转换为网络字节顺序并使用 ntohl()/htonl() 工作吗?
二。打包结构在 x86、x64 和 arm 上的大小是否相同?
三。这种方法有什么固有的弱点吗?
struct __attribute__((packed)) Header {
uint8_t magic;
uint8_t flags;
};
struct __attribute__((packed)) Record {
uint64_t length;
uint32_t crc;
uint16_t year;
uint8_t day;
uint8_t month;
uint8_t hour;
uint8_t minute;
uint8_t second;
uint8_t type;
};
我使用的测试代码开发格式:
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <limits.h>
#include <strings.h>
#include <stdint.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
struct __attribute__((packed)) Header {
uint8_t magic;
uint8_t flags;
};
struct __attribute__((packed)) Record {
uint64_t length;
uint32_t crc;
uint16_t year;
uint8_t day;
uint8_t month;
uint8_t hour;
uint8_t minute;
uint8_t second;
uint8_t type;
};
int main(void)
{
int fd = open("test.dat", O_RDWR|O_APPEND|O_CREAT, 444);
struct Header header = {1, 0};
write(fd, &header, sizeof(header));
char msg[] = {"BINARY"};
struct Record record = {strlen(msg), 0, 0, 0, 0, 0, 0, 0};
write(fd, &record, sizeof(record));
write(fd, msg, record.length);
close(fd);
fd = open("test.dat", O_RDWR|O_APPEND|O_CREAT, 444);
read(fd, &header, sizeof(struct Header));
read(fd, &record, sizeof(struct Record));
int len = record.length;
char c;
while (len != 0) {
read(fd, &c, 1);
len--;
printf("%c", c);
}
close(fd);
}
【问题讨论】:
-
我投票关闭,因为太宽泛了,所以 - 抱歉,尝试不同的网站!
-
@Olaf:我会投票保留:这是一个非常实用的现实问题,一直在出现。仅仅因为它没有一个简单的答案并不意味着它不值得考虑。 (话虽如此,但我不是一个普通人,所以如果大家一致认为有一些实际的、现实世界的编程问题是这个网站不解决的,那么我就在没有立场争论。)
-
@SteveSummit:我确实同意这个问题实际上很有趣(请注意我的“对不起”)。但是,这对于 SO 来说是题外话。我真的希望 OP 找到另一个站点(不确定,是否有一个堆栈交换)。投票:嗯,这显然是我的意见。如果其他人的想法不同,它将保持打开状态。我可以忍受。
-
"不终止 null 以节省空间"...真的吗?终止 NULL 字节是每个字符串的单个字节。您的替代方法是存储一个长度,它可以是一个字节,但这会将字符串限制为 256 个字节或更少。更有用的是,长度将是多个字节,这实际上比终止 NULL 使用更多空间...