字节序与比特序详解

2023-05-16

  • 字节序的定义
    • 几种类型的字节序
      • cpu字节序
      • 外部bus字节序
      • 设备字节序
      • 网络协议字节序
        • Ethernet协议字节序
        • IP协议字节序
      • 编译字节序
  • 比特序的定义
  • 字节序与bit序的转换
  • 结构体的位域

字节序的定义

字节序就是说一个对象的多个字节在内存中如何排序存放,比如我们要想往一个地址a中写入一个整形数据0x12345678,那么最后在内存中是如何存放这四个字节的呢?
 0x12这个字节值为最高有效字节,也就是整数值的最高位(在本文中0x12=0x12000000),0x78为最低有效字节。
 这里就分为大端字节序和小端字节序
 大端字节序:便是指最高有效字节落在低地址上的字节存放方式
 小端字节序:便是指最高有效字节落在高地址上的字节存放方式。
 a a+1 a+2 a+3
0x12 0x34 0x56 0x78 大端字节序
0x78 0x56 0x34 0x12 小端字节序

几种类型的字节序

参考如下图的计算机系统:
这里写图片描述
CPU, local bus and internal memory/cache 都可以归纳为CPU,因为他们通常都有同样的字节序。

cpu字节序

小端字节序CPU包括Intel和DEC,大端字节序CPU包括Motorola 680x0,Sun Sparc以及IBM(例如Powerpc)。MIPS和ARM可以配置两种字节序中的任一种。

外部bus字节序

bus的字节序由bus协议定义,假如bus的字节序和CPU字节序不同,bus控制器或者桥会执行转换工作。

设备字节序

Kevin’s Theory #1: When a multi-byte data unit travels across the boundary of two reverse endian systems, the conversion is made such that memory contiguousness to the unit is preserved.

网络协议字节序

网络协议的字节序定义了网络协议头中整形域部分的字节和比特是如何发送和接收的。我们引入一个术语:线上地址(wire address).低位线上地址的比特或者字节在高位之间传输。
网卡通常遵循它们支持的网络协议的字节序。大多数网络协议是大端字节序。我们以Ethernet协议和IP协议为例说明。

Ethernet协议字节序

以太网(Ethernet)协议是大端字节序。这意味着一个整型值的高字节被放置在低线上地址上,同时在低字节之前被传输或者接收。例如arp协议字0x0806,在以太网头中的布局如下:
wire byte offset: 0 1
hex : 08 06
同时注意到以太网头中的mac地址被认为是字符串,因此不用关心字节序的问题。I例如mac地址12:34:56:78:9a:bc在线上有如下布局,字节12被首先传输。
这里写图片描述
以太网的数据结构如下:

struct ethhdr
{
        unsigned char   h_dest[ETH_ALEN];       
        unsigned char   h_source[ETH_ALEN];     
        unsigned short  h_proto;                
};

h_dest 和h_source 是字符串,因此不必考虑字节序的问题。h_proto是整型值,因此在主机访问该字段是需要使用ntohs,在主机填充该字段时要htons。
至于比特序的传输顺序下文有介绍。

IP协议字节序

IP协议字节序是大端。bit序继承自CPU的,网卡负责线上转换bit序列。
以下为ip header的结构体:

struct iphdr {
#if defined(__LITTLE_ENDIAN_BITFIELD)
        __u8    ihl:4,
                version:4;
#elif defined (__BIG_ENDIAN_BITFIELD)
        __u8    version:4,
                ihl:4;
#else
#error  "Please fix <asm/byteorder.h>"
#endif
        __u8    tos;
        __u16   tot_len;
        __u16   id;
        __u16   frag_off;
        __u8    ttl;
        __u8    protocol;
        __u16   check;
        __u32   saddr;
        __u32   daddr;
        /*The options start here. */
};

version 和 ihl 字段:
根据ip协议,version是ip头首字节的高有效4bit ,ihl是低有效bit.
有两种方法访问这两个字段:
1.直接解析法
假如ver_ihl代表ip头的首字节则ipl=ver_ihl&0xf,version=ver_ihl>>4,不论主机是那种字节序。
2.结构体位域法
定义如上的结构体,假如主机是小端,我们定义ihl在version之前,如果是大端正好相反。应用Kevin’s Theory #2 如果位域A定义在位域B之前,那么位域A总是出现在低序的比特位。正好可以满足我们的访问要求。

编译字节序

CPU的字节序影响CPU的指令集。不同的GNC C工具链为了编译C代码应该使用相应CPU的大小端。例如mips-linux-gcc和mipsel-linux-gcc是被用来分别编译大端的和小端的MIPs代码。

比特序的定义

比特序就是一个字节中的bit顺序问题。一般情况下系统的比特序和字节序是保持一致的。 对应分为以下情况:
LSB 0 位序:字节的第0位存放数据的least significant bit,即我们的数据的最低位存放在字节的第0位。(对应小端字节序)
MSB 0 位序:节的第0位存放数据的most significant bit,即我们的数据的最高位存放在字节的第0位。(对应大端字节序)
LSB是指 least significant bit,MSB是指 most significant bit。
比特序1 0 0 1 0 0 1 0在大端系统中最高有效比特位为1、最低有效比特位为0,字节的值为0x92。在小端系统中最高、最低有效比特位则相反为0、1,字节的值为0x49。
跟字节序类似,要想保持一个字节值不变那么就要使系统能正确的识别最高、最低有效比特位。

字节序与bit序的转换

字节序转换函数ntohl(s)、htonl(s) 。
例如在socket编程中经常要用到网络字节序转换函数ntohl、htonl来进行主机序和网络序(大端序)的转换,在主机序为小端的系统中字节序列78 56 34 12(val=0x12345678)经过htonl转换后字节序列变成12 34 56 78
字节序转换后我在想是不是比特序也一同进行了转换?
 为什么会有这个疑问呢,因为前文可知系统的比特序和字节序是一致的,现在字节序已经从小端变成了大端那么比特序应该也要一起转换。而且如果比特序不变化那么当这些字节到了目标大端序系统中后每一个字节的值都会发生变化,因为同样的比特序列在小端和大端系统中识别的字节值会不一样。
 首先从htonl、ntohl的源码来看确实只进行了字节序的转换并没有进行比特序的转换,再有就是以前socket编程的时候只调用了ntohl、htonl等函数并没有调用(而且系统也没有提供)比特序转换函数,但是最后的结果都是正确的,并没有发现上面提到的字节值发生变化的问题。
 这是因为系统帮我们自动做了转换。下面进行详细分析。
 比特的发送、接收顺序是指一个字节中的bit在网络电缆中是如何发送、接收的。在以太网(Ethernet)中,是从最低有效比特位到最高有效比特位的发送顺序,也就是最低有效比特位首先发送。
 在以太网中这个规定有点奇怪,因为字节序我们是按照大端序来发送,但是比特序却是按照小端序的方式来发送。如下图所示:
 主机是大端系统:
这里写图片描述
 比特的发送、接收顺序对CPU、软件都是不可见的,(对诸如PHY的serdes(串行器和解串器)以及网卡写总线的硬件设计是非常重要的)因为我们的网卡会给我们处理这种转换,在发送的时候按照小端序发送比特位,在接收的时候网卡会把接收到的比特序转换成主机的比特序
 The bit transmission/reception order generally is invisible to the CPU and software, 下面是一个小端机器发送一个int整型给一个大端机器的示意图:
这里写图片描述

结构体的位域

对于位域有一个约定:在C语言的结构体中如果包含了位域,如果位域A定义在位域B之前,那么位域A总是出现在低序的比特位。
参考如下代码:

#include<stdio.h>

struct bit_order{
    unsigned char a: 2,
                  b: 3,
                  c: 3;
};

int main(int argc, char *argv[])
{
    unsigned char ch      = 0x79;
    struct bit_order *ptr = (struct bit_order *)&ch;

    printf("bit_order->a : %u\n", ptr->a);
    printf("bit_order->b : %u\n", ptr->b);
    printf("bit_order->c : %u\n", ptr->c);

    return 0;
}

小端机器A上的结果

bit_order->a : 1 
bit_order->b : 6 
bit_order->c : 3 

对应字节上的bit序如下图:
这里写图片描述
大端机器上的结果

bit_order->a : 1 
bit_order->b : 7 
bit_order->c : 1

这里写图片描述
 从上面的输出可以看到同样的代码在不同的机器中输出了不同的结果,也就是说我们的代码在不同的平台不能直接移植,导致这个问题的原因就是我们前面提到的关于位域的一个约定,定义在前面的位域总是出现在低地址的bit位中,因为不同的平台的比特序是不同的,但是我们定义的位域没有根据平台的大小端进行转换,最后就导致了问题。那么如何解决这个问题,那就是在定义结构体中的位域时判断平台的大小端:

#include<stdio.h>
#include<asm/byteorder.h>

struct bit_order{
#if defined(__LITTLE_ENDIAN_BITFIELD)
    unsigned char a: 2,
                  b: 3,
                  c: 3;
#elif defined (__BIG_ENDIAN_BITFIELD)
    unsigned char c: 3,
                  b: 3,
                  a: 2;
#else
#error  "Please fix <asm/byteorder.h>"
#endif
};

int main(int argc, char *argv[])
{
    unsigned char ch      = 0x79;
    struct bit_order *ptr = (struct bit_order *)&ch;

    printf("bit_order->a : %u\n", ptr->a);
    printf("bit_order->b : %u\n", ptr->b);
    printf("bit_order->c : %u\n", ptr->c);

    return 0;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

字节序与比特序详解 的相关文章

  • BIO与NIO的方式实现文件拷贝

    面试题 编程实现文件拷贝 xff08 这个题目在笔试的时候经常出现 xff0c 下面的代码给出了两种实现方案 xff09 span class hljs keyword import span java io FileInputStream
  • 一路(16)走来,一起(17)依然同行

    来个自我介绍吧 xff0c 我叫 xff0c 计算机科学与技术专业 xff0c 本科 xff0c 这句话应该是16年整整一年说过最多的 那么我去年整整一年我又有那些收获呢 xff0c so xff0c 我也来个年终总结 xff0c 年初展望
  • 电路城(www.cirmall.com)-学习IoT,BLE编程绝佳平台,nRF52832 BLE(蓝牙低能耗)开发板

    该nRF52832 BLE xff08 蓝牙低能耗 xff09 开发板是一款具有温度 xff0c 湿度 xff0c 环境光和加速度传感器的蓝牙低能耗开发板 该蓝牙开发板具有ARM Cortex M4F CPU的nRF52832 BLE So
  • Linux上jmeter-server启动失败

    贴个广告 楼主的博客已全部搬迁至自己的博客 xff0c 感兴趣的小伙伴请移步haifeiWu与他朋友们的博客专栏 Jmeter server启动失败 xff1a Cannot start Unable to get local host I
  • Mysql的七种join

    对于SQL的Join xff0c 在学习起来可能是比较乱的 我们知道 xff0c SQL的Join语法有很多inner的 xff0c 有outer的 xff0c 有left的 xff0c 有时候 xff0c 对于Select出来的结果集是什
  • shell脚本实现自动保留最近n次备份记录

    贴个广告 楼主的博客已全部搬迁至自己的博客 xff0c 感兴趣的小伙伴请移步haifeiWu与他朋友们的博客专栏 项目中出现的问题 某天上午服务器出现卡顿特别严重 xff0c 页面加载速度奇慢 xff0c 并且某些页面刷新出现404的问题
  • Java实现终止线程池中正在运行的定时任务

    贴个广告 楼主的博客已全部搬迁至自己的博客 xff0c 感兴趣的小伙伴请移步haifeiWu与他朋友们的博客专栏 源于开发 最近项目中遇到了一个新的需求 xff0c 就是实现一个可以动态添加定时任务的功能 说到这里 xff0c 有人可能会说
  • TCP 粘包问题浅析及其解决方案

    最近一直在做中间件相关的东西 xff0c 所以接触到的各种协议比较多 xff0c 总的来说有TCP xff0c UDP xff0c HTTP等各种网络传输协议 xff0c 因此楼主想先从协议最基本的TCP粘包问题搞起 xff0c 把计算机网
  • Redis协议规范(译文)

    原文地址 xff1a haifeiWu的博客 博客地址 xff1a www hchstudio cn 欢迎转载 xff0c 转载请注明作者及出处 xff0c 谢谢 xff01 Redis客户端使用名为RESP xff08 Redis序列化协
  • Netty 源码中对 Redis 协议的实现

    原文地址 xff1a haifeiWu的博客 博客地址 xff1a www hchstudio cn 欢迎转载 xff0c 转载请注明作者及出处 xff0c 谢谢 xff01 近期一直在做网络协议相关的工作 xff0c 所以博客也就与之相关
  • 高性能无锁队列 Disruptor 初体验

    原文地址 xff1a haifeiWu和他朋友们的博客 博客地址 xff1a www hchstudio cn 欢迎转载 xff0c 转载请注明作者及出处 xff0c 谢谢 xff01 最近一直在研究队列的一些问题 xff0c 今天楼主要分
  • Vultr(云服务器)安装GUI图形化界面(已解决)

    服务器 xff1a Vultr OS xff1a Ubuntu 14 04 步骤 xff1a 1 远程登陆到服务器 2 确保所有的包和依赖关系是最新的 apt span class hljs keyword get span update
  • WorkerMan客户端连接失败

    workerman客户端连接失败 今天访问客服聊天功能发现不能发送信息 xff0c 然后看到是因为 WebSocket 连接失败 xff0c 图如下 xff1a 根据字面意思已经了解了问题是因为连接拒绝 xff0c 那么为什么会拒绝呢 xf
  • 2020计算机技术类,部分人工智能与软件工程SCI一区期刊列表(基于letpub数据)

    网上找了很久将计算机技术作为独立大区的期刊列表 xff0c 还是没有找到 所以我决定根据letpub的数据 xff0c 自己整理下 xff0c 方便以后查看 注 xff1a 由于2020与2019年的数据存在一些冲突 xff0c 部分数据可
  • IoT -- 解读物联网四层架构

    本文以物联网四层架构为基础 xff0c 从物联网产品设计的角度来解读每层架构的功能以及主要内容 xff0c 旨在为物联网产品设计以及实现思路感兴趣的物联网产品或研发人员有些帮助 通过互联网 xff0c 人和人之间可以传递和交流信息 物联网
  • 【putty无法连接Linux-centos7】

    一 二 1 vmware中打开虚拟机 xff0c 选择网络适配器 xff0c 选择模式 选择桥接模式 xff0c 则跟电脑主机一样使用以太网 xff0c 可以联网 xff0c 也可以ping通其他主机 xff0c 选择vmnet8 NAT模
  • 我的视觉SLAM学习的小小入门---Ubuntu18配置VINS-MONO

    前言 作为一名才接触视觉SLAM的菜鸟 xff0c 除了捧着高翔老师的书看着那晦涩难懂的代码与理论 xff0c 就是跟着高翔老师的课程囫囵吞枣地学着 但是似乎总不见成效 xff0c 时常想象着何时可以像大佬们一样建图 Vins mono可算
  • 关于Ubuntu(Debian)软件源报错问题及解决

    问题 xff1a 在执行sudo apt get update时出现以下报错 xff0c 查询得知是因为换源以后 xff0c 新的下载源没有公钥 W GPG error http mirrors aliyun com debian bust
  • Cmake常用指令

    1 SET SET lt variable gt lt value gt CACHE lt type gt lt docstring gt FORCE 将缓存条目variable设置为值 lt value gt xff0c 除非用户进行设置
  • [LeetCode] Two Sum 两数之和 java实现 C++实现

    LeetCode Two Sum 两数之和 java实现 C 43 43 实现 Given an array of integers return indices of the two numbers such that they add

随机推荐

  • FreeRTOS学习总结 (一)

    FreeRTOS学习总结 一 移植 上图是从FreeRTOS官网下载的源文件目录 xff0c 移植所需要的文件都在Source文件夹下 如上图 xff0c 在工程文件夹下创建FreeRTOS文件夹 xff0c 子文件夹和相应文件 xff0c
  • FreeRTOS学习总结 (二)

    FreeRTOS学习总结 四 软件定时器 软件计时器由FreeRTOS内核实现 xff0c 并在其控制之下 它们不需要硬件支持 xff0c 也与硬件计时器或硬件计数器无关 软件计时器功能是可选的 要使用软件计时器功能 xff1a 1 构建F
  • 网络编程及三大协议(TCP + UDP + Http)

    网络编程及三大协议 xff08 TCP 43 UDP 43 Http xff09 一 网络编程 1 计算机网络 是指将地理位置不同的具有独立功能的多台计算机及其外部设备 xff0c 通过通信线路连接起来 xff0c 在网络操作系统 xff0
  • 仿真软件GCKontorl之软件在环(SiL)仿真

    摘要 xff1a 软件在环SiL Software in the Loop 仿真 xff0c 是将仿真工程中的某些仿真模型或控制策略 xff0c 采用写手代码替代 xff0c 完成软件在环 SiL 的仿真测试及验证 特别是C语言在嵌入式系统
  • [数学建模]数学建模算法和模型(B站视频)(一)

    数学建模 数学建模算法和模型 xff08 B站视频 xff09 xff08 一 xff09 层次分析法 层次分析法 xff0c 简称AHP xff0c 是指将与决策总是有关的元素分解成目标 准则 方案等层次 xff0c 在此基础之上进行定性
  • 决策树的各类概述

    LogisticRegression 1 决策树的前世今生1 1 什么是决策树1 2 决策树的构建1 3 sklearn中使用决策树 2 决策树的特征选择2 1 信息论相关概念2 2 信息熵2 3 条件熵2 4 信息增益2 5 信息增益率2
  • 事件流及其三阶段

    事件流 1 事件的捕获阶段 2 事件的目标阶段 3 事件的冒泡阶段 事件有三个阶段 xff0c 首先发生的是捕获阶段 xff0c 然后是目标阶段 xff0c 最后才是冒泡阶段 xff0c 对于捕获和冒泡 xff0c 我们只能干预其中的一个
  • 卡尔曼滤波

    这篇文章完全是我自己为了记录一下自己对于KF的印象 xff0c 表层的不能再表层了 如果是需要详细了解KF的请去阅读高手的文章 xff0c 不要在此篇上浪费时间 前言 xff1a 在读一些文章的时候 xff0c 总会看到研究方法基于卡尔曼滤
  • Nvidia Jetson TX2入门指南(白话版)

    最近要用到jetson tx2 xff0c 但之前也完全没有接触过 边用边学 xff0c 这篇文章就是向新手介绍下jetson tx2刚入手的一些事项 适合纯小白 一 TX2初认识 开发板全称 xff1a Nvidia Jetson tx2
  • Nvidia Jetson TX2+Intel Realsense D435i跑ORB_SLAM3

    前言 xff1a 网上的教程实在是太多 xff0c 从诸多教程中找到一个适合自己的实属不易 将此记录下来 xff0c 希望能够帮助到有需要的人 因为时间紧迫 xff0c 没时间写特别详细的内容 xff0c 只能引用一些他人的步骤 请见谅 x
  • catkin_make

    普通情况下编译文件都是使用cmake make工具 xff0c 与此有关的内容可以参考 xff1a cmake CMakeLists txt make makefile的关系 但ROS中还有catkin make xff0c 不清楚他们之间
  • Airsim仿真

    Airsim设计的目的 xff1a 1 现实世界开发测试自动驾驶车辆算法费时费力 2 迎合AI的发展 xff0c 需要在各种条件下和环境下收集大量带注释训练数据 模块化设计 xff0c 强调可扩展性 提供很多API xff0c 核心组件包括
  • 0404---通过SSH连接远程服务器运行图形界面程序问题

    远程运行 linux 服务器图形界面程序问题 通常部署在数据中心机房中的服务器是没有图形桌面的 xff0c 对服务器的日常运维也往往通过远程客户端命令窗口来进行 xff0c 但有时候往往需要在服务器上远程安装或运行图形窗口类软件 xff0c
  • Jetson NX emmc版本系统转移到SSD

    因emmc版本的NX自带内存不够大 xff0c 只有16GB xff08 手上的是这个型号 xff09 xff0c 安装系统大概需要除去4G多内存 xff0c 再安装CUDA cuDNN TensorRT等内存直接爆满 无法继续使用 所以需
  • ssh远程登录报错:kex_exchange_identification: Connection closed by remote host

    基本信息 系统 xff1a MacOS Catalina 10 15 7 报错信息 xff1a 终端登录远程 服务器 时报错 xff1a kex exchange identification Connection closed by re
  • 如何在Windows的cmd下让程序在后台执行

    如何在Windows的cmd下让程序在后台执行 xff1f Hu Dennis 2008 12 24 在windows下启动JBoss服务器 xff0c 需要在命令行中输入run bat 但是运行后如果你想停止服务器 xff0c 可能的做法
  • 嵌入式LINUX识别U盘的问题

    我试过mount U盘 当开机后mount 第一个U盘时 xff0c 一般设备名为sda xff0c 然后umount xff0c 并重插另外一个U盘 xff0c 再mount xff0c 发现设备名变为sdb了 此试验进行了几次 xff0
  • yolov4+deepsort(yolo目标检测+自适应卡尔曼滤波追踪+毕业设计代码)

    项目介绍 该项目一个基于深度学习和目标跟踪算法的项目 xff0c 主要用于实现视频中的目标检测和跟踪 该项目使用了 YOLOv4 目标检测算法和 DeepSORT 目标跟踪算法 xff0c 以及一些辅助工具和库 xff0c 可以帮助用户快速
  • 集成学习(含常用案列)

    集成学习原理 xff1a 工作原理是生成多个分类器 模型 xff0c 各自独立地学习和作出预测 这些预测最后结合成组合预测 xff0c 因此优于任何一个单分类的做出预测 集成学习算法分类 xff1a 集成学习算法一般分为 xff1a bag
  • 字节序与比特序详解

    字节序的定义 几种类型的字节序 cpu字节序外部bus字节序设备字节序网络协议字节序 Ethernet协议字节序IP协议字节序 编译字节序 比特序的定义字节序与bit序的转换结构体的位域 字节序的定义 字节序就是说一个对象的多个字节在内存中