理解字节序 大端字节序和小端字节序

摘要:
例如,值0x2211存储在两个字节中:高字节为0x22,低字节为0x11。同样,大端字节顺序和小端字节顺序0x1234567的写入如下。因此,计算机的内部处理是小端字节顺序。外部设备可以自行处理字节顺序问题。在不同的CPU平台上,字节顺序转换示例通常不同。接下来,编写一个简单的C程序,可以在不同的平台上测试字节顺序。Htonl将i_当num转换为网络字节顺序时,可以看出网络字节顺序是大端法。

以下内容参考了

http://www.ruanyifeng.com/blog/2016/11/byte-order.html

https://blog.csdn.net/yishengzhiai005/article/details/39672529

计算机硬件有两种储存数据的方式:大端字节序(big endian)和小端字节序(little endian)。

举例来说,数值0x2211使用两个字节储存:高位字节是0x22,低位字节是0x11。

大端字节序:高位字节在前,低位字节在后,这是人类读写数值的方法。
小端字节序:低位字节在前,高位字节在后,即以0x1122形式储存。

同理,0x1234567的大端字节序和小端字节序的写法如下图。

请输入图片描述

我一直不理解,为什么要有字节序,每次读写都要区分,多麻烦!统一使用大端字节序,不是更方便吗?

上周,我读到了一篇文章,解答了所有的疑问。而且,我发现原来的理解是错的,字节序其实很简单。

首先,为什么会有小端字节序?

答案是,计算机电路先处理低位字节,效率比较高,因为计算都是从低位开始的。所以,计算机的内部处理都是小端字节序。

但是,人类还是习惯读写大端字节序。所以,除了计算机的内部处理,其他的场合几乎都是大端字节序,比如网络传输和文件储存。

计算机处理字节序的时候,不知道什么是高位字节,什么是低位字节。它只知道按顺序读取字节,先读第一个字节,再读第二个字节。

如果是大端字节序,先读到的就是高位字节,后读到的就是低位字节。小端字节序正好相反。

理解这一点,才能理解计算机如何处理字节序。

字节序的处理,就是一句话:

"只有读取的时候,才必须区分字节序,其他情况都不用考虑。"

处理器读取外部数据的时候,必须知道数据的字节序,将其转成正确的值。然后,就正常使用这个值,完全不用再考虑字节序。

即使是向外部设备写入数据,也不用考虑字节序,正常写入一个值即可。外部设备会自己处理字节序的问题。

字节序转换的例子

不同cpu平台上字节序通常也不一样,下面写个简单的C程序,它可以测试不同平台上的字节序。

#include <stdio.h>
#include <netinet/in.h>
int main()
{
    int i_num = 0x12345678;
    printf("[0]:0x%x
", *((char *)&i_num + 0));
    printf("[1]:0x%x
", *((char *)&i_num + 1));
    printf("[2]:0x%x
", *((char *)&i_num + 2));
    printf("[3]:0x%x
", *((char *)&i_num + 3));
 
    i_num = htonl(i_num);
    printf("[0]:0x%x
", *((char *)&i_num + 0));
    printf("[1]:0x%x
", *((char *)&i_num + 1));
    printf("[2]:0x%x
", *((char *)&i_num + 2));
    printf("[3]:0x%x
", *((char *)&i_num + 3));
 
    return 0;
} 

在80X86CPU平台上,执行该程序得到如下结果:

[0]:0x78 
[1]:0x56 
[2]:0x34 
[3]:0x12

[0]:0x12 
[1]:0x34 
[2]:0x56 
[3]:0x78

分析结果,在80X86平台上,系统将多字节中的低位存储在变量起始地址,使用小端法。htonl将i_num转换成网络字节序,可见网络字节序是大端法。

免责声明:文章转载自《理解字节序 大端字节序和小端字节序》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇linux下把一个用户从某个组中删除,而不删除用户常用运放选型一览表下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

python+NLTK 自然语言学习处理四:获取文本语料和词汇资源

在前面我们通过fromnltk.bookimport*的方式获取了一些预定义的文本。本章将讨论各种文本语料库 1古腾堡语料库 古腾堡是一个大型的电子图书在线网站,网址是http://www.gutenberg.org/。上面有超过36000本免费的电子图书,因此也是一个大型的预料库。NLTK也包含了其中的一部分 。通过nltk.corpus.gutenbe...

Scala基础之集合(数组)

集合介绍 Scala的集合有三大类:序列Seq、集Set、映射Map,所有的集合都扩展自Iterable特质。对于几乎所有的集合类,Scala都同时提供了可变和不可变的版本。 集合可变,不可变的区别 Scala默认提供的集合都是不可变。 不可变:增删改 都会返回有个新数组 可变:可增删改  可变: scala.collection.mutable ha...

通过尾递归避免栈溢出

JavaScript中的递归即函数内调用函数自身,但递归是非常耗内存的,每一次调用都会分配一定的栈空间,达到一定的数量(具体看浏览器)便会溢出报错。 function recursion (num) { if (num === 1) { return 1; } return num + recursion(--num...

设计统计英文字母出现频率的程序的感想

  今天下午我们在学习Java的过程中,王老师给我们留下了一个程序设计作业,其要求是让我们设计一个程序,要实现 输出单个文件中的前 N 个最常出现的英语单词,并将结果输入到文本文件中的功能。我思考并上机了一个下午最终实现了部分功能。   首先当看到这个题目的时候,我想到了将这个实验分成三部分:   1.读取指定文本的内容;   2.统计所有单词在该文本中的...

2021团体程序设计天梯赛 L1-6 吉老师的回归

思路: 字符串处理 Tip: getline和find的应用 #include <bits/stdc++.h> using namespace std; int main() { int n, t, num = 0; string now; cin >> n >> t; getcha...

多种方式实现字符串/无符号数反向输出_栈_递归_头尾指针

1、递归调用方式实现无符号数反向输出 C语言实现(DEV c++4.9.9.2运行通过) #include<stdio.h> void reverse_print(unsigned long num) { if(num==0) return; printf("%d",num%10); //输出最低位...