大端和小端传输字节序

2023-12-23 21:04
文章标签 字节 传输 小端 大端

本文主要是介绍大端和小端传输字节序,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

大端和小端传输字节序

  • 大端和小端
    • 一、最高有效位、最低有效位
      • 1.MSB(Most significant Bit)最高有效位
      • 2.LSB(Least Significant Bit)最低有效位
    • 二、内存地址
    • 三、大端和小端
    • 四、网络字节序和主机字节序
    • 五、C#位操作符
    • 六、C#中关于大端和小端的转换
    • 七、关于负数
    • 八、关于汉字编码以及与字节序的关系
      • 网络通讯
      • 文件

大端和小端

在计算机中是以字节为单位,每一个地址对应一个字节,一个字节8bit。在C中,除了8bit的char以外,还有16bit的short,32位的int,64位long,当然具体要由编译器决定,可以通过sizeof来获取不同类型在内存中占用的字节数。在计算机系统中,当物理单位的长度大于1个字节时,就要区分字节顺序。常见的字节顺序有两种:Big Endian(High-byte first) 和 Litter Endian(Low-byte first),当然还有其他字节顺序,但不常见,例如Middle Endian。

一、最高有效位、最低有效位

要理解Big Endian和Little Endian,首先要搞清楚MSB和LSB。

1.MSB(Most significant Bit)最高有效位

在一个n位二进制数字中n-1位,也就是最左边的位。

2.LSB(Least Significant Bit)最低有效位

指最右边的位。
例如:一个int类型的整形123456789
二进制表达方式: 0000 0111 0101 1011 1100 1101 0001 0101(从右向左,每4bit对齐,最左边(高位)不够用0补齐)

十六进制表达方式:0 7 5 B C D 1 5
按照上述关于MSB和LSB的意思,在二进制表达方式中,bit从0开始,从右向左,bit 0位最低有效位,而bit 23为最高有效位。而我们一般称左边的0x07为高位字节,0x15为低位字节。
再通俗一点解释就是:8421的,8这端为高位,1这端为低位,相应的字节则分别称为高位字节和低位字节。

二、内存地址

在内存中,多字节对象都是被存储为连续的字节序列。例如在C语言中,一个类型为int的变量n,如果其存储的首个字节的地址为0x1000,那么剩余3个字节地址将存储在0x1001~0x1003。总之,不管具体字节顺序是以什么方式排列,内存地址的分配一般是从小到大的增长。 我们常把0x1000称为低地址端,把0x1003称为高地址端。

三、大端和小端

搞清楚MSB、LSB、高位字节、低位字节之后,再理解大端和小端,就相当容易了,先看看概念:
小端Little Endian:低字节存放在低地址,低位字节排放在内存的低地址端,高位字节排放在内存的高地址端。
大端Big Endian:高字节存放在低地址,即高位字节排放在内存的低地址端,低位字节排放在内存的高地址端。

以二节中的例子int类型整数123456789位例:
小端在内存中排列: 0x15 0xCD 0x5B 0x07(低位在前)
大端在内存中排列: 0x07 0x5B 0xCD 0x15(高位在前)

从例子中可以看出小端比较符合人的思维,而大端则看上去非常直观。
注:

  1. 例子中是假设编译器支持int为32位的前提下,如果是16位,那大端的排列则为0xCD 0x15 0x07 0x5B
  2. 大小端一般是由CPU架构决定,常见的Intel、AMD的CPU使用的是小端字节,而PowerPC使用的是大端字节序,有些ARM处理器还可以选择大端还是小端模式,具体自行查阅。
  3. C#中,字节序跟编译平台所在的CPU相关,例如在Intel x86 CPU架构的windows平台中,C#采用的小端序。而Java由于JVM屏蔽不了不同CPU架构导致额字节序差异,所以默认采用大端字节。所以,大小端模式是由CPU决定,而编译器又可能会改变这种模式。

在这里插入图片描述

四、网络字节序和主机字节序

网络字节序(Network Order):TCP/IP各层协议将字节序定义为Big Endian,因此TCP/IP协议中的字节序同称之为网络字节序。
主机字节序(Host Order):整数在内存中保存的顺序,它遵循Little Endian规则(不一定,要看主机的CPU架构)。所以当两台主机之间要通过TCP/IP协议进行通信的时候就需要调用相应的函数进行主机序列(Little Endian)和网络序(Big Endian)的转换。
如果是做跨平台开发时,双方需要协商好字节序,然后根据程序运行的环境,确定是否需要字节序转换。
例如约定的通讯字节序位是Big Endian,默认的window采用的Little Endian,那收到数据后就需要做转换操作。

五、C#位操作符

这里简单记录一下C#位操作符,方便以后自己查阅,也方便理解后面的讲解。

  1. 按位与&
    1&0为0;0&0为0;1&1为1
  2. 按位与|
    1|0为1;0|0为0;1|1为1
  3. 按位取反~
    ~1为0; ~0为1;
  4. 按位异或^
    1^1为0; 0^0为0; 1^0为1;
  5. 左移<<
    位左移运算,将整个数向左移若干位,左移后空出的部分0补齐
  6. 右移>>
    位右移运算,将整个数向右移若干位,右移后空出的部分用0补齐

六、C#中关于大端和小端的转换

  1. 重复轮子
using System;namespace Framework.NetPackage.Common
{/// <summary>/// 字节序转换辅助类/// </summary>public static class Endian{public static short SwapInt16(this short n){return (short)(((n & 0xff) << 8) | ((n >> 8) & 0xff));}public static ushort SwapUInt16(this ushort n){return (ushort)(((n & 0xff) << 8) | ((n >> 8) & 0xff));}public static int SwapInt32(this int n){return (int)(((SwapInt16((short)n) & 0xffff) << 0x10) |(SwapInt16((short)(n >> 0x10)) & 0xffff));}public static uint SwapUInt32(this uint n){return (uint)(((SwapUInt16((ushort)n) & 0xffff) << 0x10) |(SwapUInt16((ushort)(n >> 0x10)) & 0xffff));}public static long SwapInt64(this long n){return (long)(((SwapInt32((int)n) & 0xffffffffL) << 0x20) |(SwapInt32((int)(n >> 0x20)) & 0xffffffffL));}public static ulong SwapUInt64(this ulong n){return (ulong)(((SwapUInt32((uint)n) & 0xffffffffL) << 0x20) |(SwapUInt32((uint)(n >> 0x20)) & 0xffffffffL));}}
}
  1. BCL库支持的函数
    System.Net.IPaddress.HostToNetworkOrder、System.Net.IPAddress.NetworkToHostOrder,这两个函数的内容实现和上面重复轮子原理一样。

七、关于负数

在计算机中,负数以及其绝对值的补码形式表示,不明白可以查阅九中贴出的相关资源。关于负数的字节序跟一般整数的字节序处理没有任何区别。

八、关于汉字编码以及与字节序的关系

  1. 对于gb2312、gbk、gb1&8030、bigs,其编码某个汉字产生的字节顺序,由某编码方案本身决定,不受CPU字节序的影响。其实这几种编码的字节序和大端模式的顺序是一致的。
    在这里插入图片描述
  2. UTF-8
    UTF-8和gb系列编码一样,其编码某个汉字产生的字节顺序,由其编码方案决定,不受CPU字节序的影响。无论一个汉字有多少个字节,它的字节序与编码顺序保持一致。
    在这里插入图片描述
  3. Unicode

Unicode只是一个符号集,它只规定了符号的二进制代码,却没有规定这个二进制代码应该如何存储。所以他没有要求如何存储编码后的字节,也就受CPU字节序的影响。

Unicode的具体实现包括UTF-16、UTF-32(当然也包括UTF-8,但由于其编码方式和编码后的字节序与其他Unicode编码实现有较大区别,所以单独拿出来讲解的)。

  1. 总结

网络通讯

在实际的网络通讯中,网络协议例如TCP是规定网络字节序(Network Order)是大端。而针对汉字具体使用什么编码,通讯双方要么提前约定好,要么就需要在数据包中标识好汉字具体使用的编码。

如果在网络通讯中,涉及例如UTF16这样区分大小端的编码,除非按网络协议要求采用大端模式是,否则也要事先约定好,或者在数据包中标识好使用的字节序模式。

文件

文件的也会存储汉字,当然也要进行编码。如果采用UTF-16这样的有字节序模式区分的编码,编码规则要求可以在文件头部的BOM(Byte Order Mark)来标记。如果没有标记,除非事先知道字节序的模式,否则只能大小端都试一遍。在这里插入图片描述

这篇关于大端和小端传输字节序的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/529458

相关文章

字节面试 | 如何测试RocketMQ、RocketMQ?

字节面试:RocketMQ是怎么测试的呢? 答: 首先保证消息的消费正确、设计逆向用例,在验证消息内容为空等情况时的消费正确性; 推送大批量MQ,通过Admin控制台查看MQ消费的情况,是否出现消费假死、TPS是否正常等等问题。(上述都是临场发挥,但是RocketMQ真正的测试点,还真的需要探讨) 01 先了解RocketMQ 作为测试也是要简单了解RocketMQ。简单来说,就是一个分

JVM - 字节码文件详解

文章目录 目录 文章目录 1. 无关性基石 2. Class类文件结构 magic- 魔数 主副版本号 常量池 访问标志 类索引,父类索引与接口索引集合 字段 方法 属性 3. 类加载机制 类的生命周期 类加载过程 加载 连接 验证 准备 解析 初始化 4. 类加载器 类与类加载器 类加载器的分类 启动类加载器  扩展类加载器 应用程序类加

远程桌面文件传输异常或者取消传输后一直显示正在取消

环境: Window Servers 2008 R2 摘要说明: 本篇文章主要讲述当应用远程桌面进行文件传输时,若因网络等导致进程中断,再次传输时则不能进行文件传输;或者传输时取消传输,然后一直显示正在取消。此时可以通过重启window的rdpclip.exe进程来解决此问题 步骤 1.关闭rdpclip.exe进程 远程桌面连上上传输异常的服务器,打开资源管理器,在进程列关闭rdpc

Java传输本地目录到远程服务器

在使用Java进行开发时,有时需要将本地目录中的文件复制或传输到远程服务器上。这种场景在部署应用程序或进行数据迁移时尤为常见。JSch库提供了一种简便的方法来实现这一功能。以下是从Codekru网站获取的信息摘要,并结合相关内容,展示如何使用JSch库实现从本地计算机复制整个目录到远程服务器的过程。 准备工作 首先,确保您的项目中已经包含了JSch库的依赖。如果您使用Maven作为构建工具,可

高效传输秘籍,揭秘Rsync和SCP的优劣,助你做出明智选择!

在日常的运维工作中,文件传输任务频繁出现,而选择合适的工具能显著提高工作效率。Rsync 和 SCP 是两款常见的文件传输工具,但它们各具优缺点,适合不同的场景。本文将通过深入分析这两款工具的特性、使用场景和性能,帮助你做出明智的选择,从而在文件传输中省时省力。 Rsync 与 SCP 简介 Rsync:增量传输的强大工具 Rsync 是一款支持文件同步的工具,广泛应用于备份和传输

SylixOS write 0 字节问题

1 问题描述 在移植中间件过程中,在SylixOS调用write函数写入0字节的数据到文件中时,会导致对应的中间件测试用例失败,失败的原因是文件系统中的write函数在Linux系统和SylixOS有区别,两种实现的差别如下。 2 write函数的实现机制 2.1 SylixOS实现机制 在SylixOS下通过write 函数写数据到普通文件中时,第一步会判断写入的数据是否为0,如果是0直

大端模式和小端模式

首先:读数据永远是从低地址开始的!!! 大端存储:低地址存放高位数据 小端存储:低地址存放低位数据 判断机器的字节序: #define _CRT_SECURE_NO_WARNINGS 1 #include <stdio.h> //判断机器字节序 int check_sys() {     int a = 1;     return *(char*)&a;//算法简化 } int main

CPU大小端字节序的检测

机器的字节序有两种,即大端字节序和小端字节序。 大端字节序:在内存中,低地址存放数据的 高位,高地址存放数据的 低位 小端字节序:在内存中,低地址存放数据的 低位,高地址存放数据的 高位 如例:定义数据  a = 0x01020304 小端方式:01 02 03 04 大端方式:04 03 02 01 那么如何判断呢,方式如下--> 一、 指

68-java字符流和字节流

Java中的字符流和字节流是用于处理输入/输出的两大类。字符流主要用于处理字符数据,而字节流可以处理任何类型的数据。 字符流: Reader:用于读取字符流的抽象类。 Writer:用于写入字符流的抽象类。 字节流: InputStream:用于读取字节流的抽象类。 OutputStream:用于写入字节流的抽象类。 下面是使用字符流和字节流的简单示例: 字符流示例(文件复

1字节的UTF-8序列的字节1无效

使用DOMReader解析XML文档时候报错”1字节的UTF-8序列的字节1无效”,我这里的解决方法。 1.手动将< ? xml version=”1.0” encoding=”UTF-8”?>中的UTF-8更改成UTF8,这样就可以了。 2.使用文本编译器把xml文档改成以UTF8无BOM编码格式就可以了。