关于单字节的字节序的问题

发布于 2022-09-18 17:03:51 字数 749 浏览 11 评论 0

一直认为 Big_endian, Little_endian 只有在多字节的数据中才有意义.
今天看 linux 网络部分的代码 关于 ip头 的定义如下:
#if defined(__LITTLE_ENDIAN_BITFIELD)
        __u8    ihl:4,
                version:4;
#elif defined (__BIG_ENDIAN_BITFIELD)
        __u8    version:4,
                ihl:4;
#else
很纳闷啊, 单字节的数据也有字节序的问题?
我在 little 下是 0x12, 难道在 big 下是 0x21

我做了个实验, 将 0x1234 用二进制打印出来:
00110100 00010010 -- 0x34 0x12
然后将 0x1234 htons 以后 再打印出来:
00010010 00110100 -- 0x12 0x34
很显然 单字节并没有因为字节序的不同而不同, 那他原代码中为什么会如此写呢?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

-黛色若梦 2022-09-25 17:03:51

一个是机器的endian,一个是网络的endian。

暗恋未遂 2022-09-25 17:03:51

说字节序只在多字节时才有意义是因为我们多数时候是使用2字节或4字节值,bit序也是有的,但CPU和网络之间会自动处理,所以编程时不关心。但IP头部的值并不都是字节的整数倍,这样的话就要考虑了。

你打印的话当然是看不出区别的,因为指令中已经自动处理了。你可以分别在Big-endian和Little-endian的计算机上用位域试一试,能看出区别来。以前做网络程序时经常要避免位域,就是比较容易出错。

[ 本帖最后由 Cyberman.Wu 于 2009-7-14 16:58 编辑 ]

自找没趣 2022-09-25 17:03:51

这个问题有时候挺让人郁闷的,其实关键在于一个标准如何统一的问题,因为大端小端已是无法逃避的问题了。
根据C语言标准里,“An implementation may allocate any addressable storage unit large enough to hold a bitfield.
If enough space remains, a bit-field that immediately follows another bit-field in a
structure shall be packed into adjacent bits of the same unit.”
关键什么叫相邻?
我们还是用硬件描述语言的思路去理解这个问题吧。
其实大端和小端并不是天壤之别,拓扑来看,不过是某些接线顺序的问题,
比如verilog,命一个16bit的wire,你会怎么命?
wire [15:0] sample;
还是
wire [0:15] sample;
无论怎么命吧,
assign sample = 16'h1234;
在两种形式下,sample的每个bit将会是什么?
于是我们再考虑,按照两种方式设计的硬件(假设上面的那个是大端,下面这个的是小端)
这个sample直接接1个16bit的ram的数据总线。
那么
struct {
unsigned char a;
unsigned char b:4;
unsigned char c:4;
} x;
这个x此时从数据总线里出来,假设就是前面的那个16'h1234,
小端的时候,
x.a代表sample[8:0],自然是0x34
s.b因为是相邻,所以代表sample[12:9],自然是0x2
s.c代表sample[16:13],自然是0x1
而大端的时候,
x.a代表sample[0:8],自然是0x12
s.b因为是相邻,所以代表sample[9:12],自然是0x3
s.c代表sample[16:13],自然是0x4
数字设计的时候我经常被这些东西搞晕掉。

锦爱 2022-09-25 17:03:51
  1. $ cat 1.c
  2. #include <stdio.h>
  3. union {
  4. unsigned short m;
  5. struct xx{
  6.         unsigned char a:7;
  7.         unsigned char b:5;
  8.         unsigned char c:4;
  9. } n;
  10. struct xxx{
  11.         unsigned short a:7;
  12.         unsigned short b:5;
  13.         unsigned short c:4;
  14. } k;
  15. }x;
  16. int main()
  17. {
  18.         x.m=0x1294;
  19.         printf("%hhx\n%hhx\n%hhx\n",x.n.a,x.n.b,x.n.c);
  20.         printf("%hx\n%hx\n%hx\n",x.k.a,x.k.b,x.k.c);
  21.         return 0;
  22. }
  23. $ gcc 1.c
  24. $ ./a.out
  25. 14
  26. 12
  27. 0
  28. 14
  29. 5
  30. 1

复制代码
恩,知道原因了,这里的x应该是4个字节。k.b是不能跨两个unsigned char的。

[ 本帖最后由 cjaizss 于 2009-7-15 22:09 编辑 ]

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文