字节序(“Endian”、”endianness” 或 “byte-order”)

字节序(“Endian”、”endianness” 或 “byte-order”)1.define字节序,或字节顺序("Endian"、"endianness"或"byte-order"),描述了计算机如何组织字节,组成对应的数字。8bit(位)=1byte(字节)CPU通过数据总线读取数据是以字长(w

大家好,欢迎来到IT知识分享网。

1.define

字节序,或字节顺序(”Endian”、”endianness” 或 “byte-order”),描述了计算机如何组织字节,组成对应的数字。

8 bit(位) = 1byte(字节)
CPU 通过数据总线读取数据是以字长(word)读取。
字长的定义是“运算中一次处理的基本元素的宽度”
在32位字长的处理器系统中,CPU一次可以读写的数据长度是32bit(位),即字长为4字节。

2.字节序分类

大端(Big Endian):高位字节存储在内存的低地址上,低位字节存储在内存的高位地址上
小端 (Little Endian):高位字节存储在内存的低地址上,低位字节存储在内存的高位地址上
image
image

大端特点:
大端模式符合人类的阅读习惯,从左至右一次进入;且符号位放在第一位,所以判断一个数是正数还是负数效率会很高,但逻辑运算会比小端模式低效。

小端特点:
大端模式的劣势正好是小端模式的优势,小端模式下,强制转换类型时不需要调整字节内容,直接取低位数据值,所以转换效率高,如把:int 类型转换为 short 类型数据。

3.为什么会有字节序

确实,如果所有平台都用同一种存储顺序,就没有字节序这一说法了

在早期, CPU 只有几千个逻辑门,小端的方式能更有效的使用逻辑电路,所以很多计算机内部计算都采用小端的方式,这种方式也就保留到了现在

另外,字节序是跟 CPU 架构相关,不同的厂家设计的规范可能都不一样,比如 Intel 的 x86 是小端方式,而 IBM 的 PowerPC 则采用大端方

大端的方式更符合人们的阅读习惯,因此大部分网络传输以及文件存储都是大端的方式

总的来说,小端主要是在计算机内部使用,大端则在外部使用

4.计算机如何处理字节序

计算机处理字节序的时候,不知道什么是高位字节,什么是低位字节。它只知道按顺序读取字节,先读第一个字节,再读第二个字节。
字节序的处理,就是一句话:”只有读取的时候,才必须区分字节序,其他情况都不用考虑。”

5.网络字节序

除非有明确说明,否则网络协议都使用大端字节序, 像 TCP/IP 就使用大端序。
还记得我们在编写网络程序的时候,传入 connect 函数实参中的 端口号吗, 传入之前需调用 htons 函数将其转成网络字节序,也就是要转成大端字节序,下面是部分代码示例

struct sockaddr_in server_addr;
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = inet_addr("192.168.1.10");
server_addr.sin_port = htons( 5000 );
connect( clientfd, (struct sockaddr *)&server_addr, sizeof(server_addr)) )

上面红色的 htons 函数的作用是将 端口号 由主机字节序转成网络字节序,网络字节序大多时候都是固定为大端字节序的,但不同的机器,主机字节序却不一样,如果本身就已经是大端了,调用 htons 函数,返回值和实参是一样的,如果本身是小端,结果会转成大端的形式

6.怎么判断大小端

根据大端和小端的特点,自己写代码获取。

#include<stdio.h>

int main()
{
    short int x;
    char x0, x1;
    x = 0x1122;
    x0 = *((char *)&x);      //把x的低位地址的值赋给x0;
    x1 = *((char *)&x + 1);      //把x的高位地址的值赋给x1;
    if( x0 == 0x11 && x1 == 0x22)
        printf(" This is big-endian \n");
    else if( x0 == 0x22 && x1 == 0x11)
        printf("This is little-endian \n");
    else
        printf("呵呵,你这个方法有误啊\n");
    return 0;
}

编译并运行,结果如下:

This is little-endian 

7.大小端转换

#小端转大端  假如:ch 和 i  是小端序

char ch[2];

int i = 0;

# x 是大端字节序
x = ch[1] << 8 | ch[0] 

# y 是大端字节序
y =   ( (i & 0xff000000) >> 24 ) |  ( (i & 0x00ff0000) >> 8 ) | ( (i & 0x0000ff00) << 8 )  | ( (i & 0x000000ff) << 24 )

i 的字节序说明:按照从左到右的顺序,把 i 的第一个字节右移 3 个字节( 24 bit ),第二个字节右移 1 字节 ( 8 bit ),第三个字节左移 1 字节 ( 8 bit ),第四个字节左移 3 个字节 ( 24 bit )

在实际的程序处理中,不应该出现字节序的问题,只有 “网络字节序” 和 “主机字节序” ,需要转换字节序时,使用 ntohl, ntohs, htonl, htons 等函数即可

ntohl       # uint32 类型 网络序转主机序
htonl       # uint32 类型 主机序转网络序

ntohs       # uint16 类型 网络序转主机序
htons       # uint16 类型 主机序转网络序

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://yundeesoft.com/30447.html

(0)

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注

关注微信