在Java中复制C结构填充
根据here,C编译器在将结构写入二进制文件时将填充值。正如链接中的示例所示,在编写这样的结构时:
struct {
char c;
int i;
} a;
对于二进制文件,编译器通常会在char和int字段之间留下一个未命名、未使用的孔,以确保int字段正确对齐
如何使用不同的语言(在我的例子中是Java)创建二进制输出文件(用C生成)的精确副本
是否有一种在Java输出中自动应用C填充的方法?或者我必须通过编译器文档来了解它是如何工作的(顺便说一下,编译器是g++的)
# 1 楼答案
这个洞是可配置的,编译器有开关将结构对齐1/2/4/8字节
所以第一个问题是:你到底想模拟哪条路线
# 2 楼答案
不仅在写入文件时如此,在内存中也是如此。事实上,结构在内存中被填充,如果结构被逐字节写入,那么填充就会出现在文件中
一般来说,很难确定地复制精确的填充方案,尽管我猜一些启发式方法会让你走得很远。如果您有用于分析的struct声明,这会有所帮助
通常,大于一个字符的字段将被对齐,以便其在结构中的起始偏移量是其大小的倍数。这意味着
short
s通常位于偶数偏移量上(假设sizeof (short) == 2
,可被2整除),而double
s位于可被8整除的偏移量上,依此类推更新:出于这样的原因(以及与endianness有关的原因),将整个结构转储到文件中通常是个坏主意。最好一个接一个地做,就像这样:
假设
put
函数只写入值所需的字节,这将向文件发出结构的无填充版本,从而解决问题。通过相应地编写这些函数,也可以确保正确的已知字节顺序# 3 楼答案
不要这样做,它很脆弱,会导致对齐和端点错误
对于外部数据,最好用字节显式定义格式,并编写显式函数,使用移位和掩码(而不是并集!)在内部和外部格式之间进行转换
# 4 楼答案
要了解互操作性,请查看ByteBuffer类
本质上,您创建一个特定大小的缓冲区,将不同类型的()变量放在不同的位置,然后在末尾调用array()来检索“原始”数据表示:
但这取决于你决定在哪里放置填充——也就是说,在不同的位置之间要跳过多少字节
为了读取从C中写入的数据,通常需要在从文件中读取的某个字节数组周围使用字节缓冲符
如果有帮助的话,我已经写了更多关于ByteBuffer
# 5 楼答案
都不是。相反,您可以显式地指定数据/通信格式并实现该规范,而不是依赖于C编译器的实现细节。你甚至不会从不同的C编译器中得到相同的输出
# 6 楼答案
在Java中读/写C结构的一种简便方法是使用javolution Struct类(参见http://www.javolution.org)。这不会帮助您自动填充/对齐数据,但它确实使处理字节缓冲区中的原始数据更加方便。如果你不熟悉javolution,那就值得一看,因为里面还有很多其他很酷的东西