将二进制结构写入文件,结果出乎意料?

3

我正在尝试将紧凑的数据结构写入二进制文件,但是如下的od -x所示,结果的排序不符合预期。我在64位Intel系统上使用gcc。有人知道为什么排序错误吗?它看起来不像是字节序问题。

#include <stdio.h>
#include <stdlib.h>

struct B {
     char a;
     int b;
     char c;
     short d;
} __attribute__ ((packed));

int main(int argc, char *argv[])
{
     FILE *fp;
     fp = fopen("temp.bin", "w");

     struct B b = {'a', 0xA5A5, 'b', 0xFF};

     if (fwrite(&b, sizeof(b), 1, fp) != 1)
          printf("Error fwrite\n");

     exit(0);
}

ASCII 61 是 'a',所以成员 b.a。ASCII 62 是'b',所以成员 b.c。很奇怪的是 0xA5A5 在序列中分散出现。

$ od -x temp.bin 
0000000 a561 00a5 6200 00ff
0000010

4
只是字节序问题。你需要读取字节a561 00a5并将其转换为00a5 a561,第二组也是同样的处理方式。 - jiveturkey
4
将数据以 bytes 的形式输出到标准输出,而不是以 16 位无符号值的形式输出。 - WhozCraig
我认为你在这里遇到了字节序问题。请尝试运行 od -t xC - Daniel Walker
这是od的输出格式[以16位整数分组并具有字节序]。尝试使用od -A x -t x1z -v temp.bin命令获取000000 61 a5 a5 00 00 62 ff 00 >a....b..< 000008 - Craig Estey
2个回答

8

od -x命令将输入分组为两个字节单位并交换它们的字节序,输出格式容易让人困惑。如果想保留字节的原始顺序,请使用-t x1参数。

$ od -t x1 temp.bin
0000000 61 a5 a5 00 00 62 ff 00
0000010

或者更容易记住的是,使用 hd(十六进制转储)而不是 od(八进制转储)。hd 的默认格式无需调整,并且它显示了十六进制和ASCII转储。
$ hd temp.bin
00000000  61 a5 a5 00 00 62 ff 00                           |a....b..|
00000008

"od" 不会交换字节序,只是在那些采用小端编码的系统上看起来像是这样。实际上,它并不会交换字节序,而是读取两个字节作为 16 位值并显示出来。这是小端编码的一个主要缺点。 - the busybee

2

od -x会输出两个小端字节。根据od命令的手册页

-x     same as -t x2, select hexadecimal 2-byte units

所以
0000000 a561 00a5 6200 00ff

在磁盘上的位置是:

0000000 61a5 a500 0062 ff00

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接