大端小端和C实现大小端字节序的转化

2023-05-16

大端小端

小端就是低位字节放在内存的低地址端,高位字节放在内存的高地址端。

大端就是高位字节放在内存的低地址端,低位字节放在内存的高地址端。

举一个例子,比如数字0x12 34 56 78(注意78才是低位字节)在内存中的表示形式为:

大端模式:

低地址 ——————>高地址

0x12 | 0x34 | 0x56 | 0x78

小端模式:

低地址 ——————>高地址(谐音,小弟弟,小低低,小端模式低位字节在低地址)

0x78 | 0x56 | 0x34 | 0x12

检测大端小端

借助联合体,我们可以检测 CPU 是大端模式还是小端模式,请看代码:

#include <stdio.h>
int main(void)
{
  union {int n;char ch;
  } data;
  data.n = 1;
  if (data.ch == 1) {printf("Little-endian\n");
  } else {printf("Big-endian\n");
  }
  return 0;
}

共用体的各个成员是共用一段内存的。

1 是数据的低位,如果 1 被存储在 data 的低字节,就是小端模式,这个时候 data.ch 的值也是 1。

如果 1 被存储在 data 的高字节,就是大端模式,这个时候 data.ch 的值就是 0。

一个例子

联合体的大小取决于最宽成员数据类型

typedef union {
  unsigned int a;
  unsigned int b;
} TEST_U1;

typedef union {
  unsigned int a;
  unsigned char b;
  unsigned short c;
} TEST_U2;

typedef struct {
  unsigned char a;
  unsigned char b;
  unsigned char c;
  unsigned char d;
} TEST_S3;

typedef union {
  unsigned int a;
  TEST_S3 b;
} TEST_U3;
// 小端模式
TEST_U1 u1;
TEST_U2 u2;
TEST_U3 u3;
u1.a = 0x12345678;
printf(“u1:a=%x,b=%x\r\n”, u1.a, u1.b);

在这里插入图片描述

u2.a = 0x12345678;
printf(“u2:b=%x,c=%x\r\n”, u2.b , u2.c);

在这里插入图片描述

u3.a = 0x12345678;
printf(“u3:ba=%x,bd=%x\r\n”, u3.b.a, u3.b.d);

在这里插入图片描述
联合体带冒号的说明:
在这里插入图片描述

ab.a本为1,但是只占1位,以%d输出时要转成int,扩展31位,int a所以有符号所以扩31个1,所以输出是-1

又一个例子

代码实例:

typedef struct {
  unsigned int data1 : 2;
  unsigned int data2 : 12;
  unsigned int data3 : 2
} TestData;

int main(void)
{
  TestData data;
  memset(&data, 0, sizeof(data));
  data.data1 = 0x7;
  data.data2 = 0x10;
  data.data3 = 0x1;
  unsigned int result = *(unsigned int *)&data;
  printf("value = 0x%.8x", result);
  return 0;
}

赋值语句data.data1 = 0x7 ,由于data1只占用2个bit(7=b111),因此这里溢出了,溢出的部分直接丢掉,等价于bit0和bit1都是1;

data.data2 =0x10 = b10000,即data2的第五个bit为1,其余bit为0,由于data2在整个结构体中占的bit是从第2bit开始到第14bit,这里等价于bit6为1其余为0

data.data3=0x1=b1,代表bit14为1

由于是小端结构,要从高地址往低地址读,result为int型的,共4个字节,

最高BYTE为bit31~bit24 =0,次高BYTE为bit23~bit16 = 0,之后的BYTE为bit15~bit8=b01000000=0x40 ,最低BYTE =b01000011=0x43

最后的结果则是0x4043
在这里插入图片描述
另一种读法如下:
在这里插入图片描述

C实现大小端字节序的转化

比如对32位int的转化,无非是以字节为单位对该32位int的4个字节进行首尾调换
而float可以根据与int共用联合体后,对联合体的int做转化。

#include <iostream>

using namespace std;

// 从低地址到高地址打印
void JdugeByteOrder(int *a)
{
    char *p = (char *)a;
    for (int i = 0; i < sizeof(int); i++) {
        int b = p[i];
        cout << hex << b << "\t";
    }
    cout << endl;
}

// 在原地址上进行对调来获取
void ExchangeByteOrder(int *pData)
{
    char *p = (char *)pData;
    for (int i = 0, j = sizeof(int) - 1; i < j; i++, j--) {
        int temp = p[i];
        p[i] = p[j];
        p[j] = temp;
    }
}

// 在新值地址上对调来获取 
int ExchangeByteOrder(int pData)
{
    char *p = (char *)&pData;
    for (int i = 0, j = sizeof(int) - 1; i < j; i++, j--) {
        int temp = p[i];
        p[i] = p[j];
        p[j] = temp;
    }
    return pData;
}

// 获取一个32位int类型转换后的新值
int swapInt32(int value)
{
	return ((value & 0x000000FF) << 24) |
			((value & 0x0000FF00) << 8) |
			((value & 0x00FF0000) >> 8) |
			((value & 0xFF000000) >> 24) ;
}

union intWithFloat {
	int m_i32;
	float m_f32;
};

// 获取一个32位float类型转换后的新值
float swapFloat32(float value)
{
    intWithFloat i;
    i.m_f32 = value;
    i.m_i32 = swapInt32(i.m_i32);
    return i.m_f32;
}

int main(void)
{
    int num = 0x12345678;
    //printf("%x\n", num);
    cout << hex << num << endl;
    printf("before ExchangeByteOrder, num:\n");
    JdugeByteOrder(&num);
    ExchangeByteOrder(&num);
    printf("after ExchangeByteOrder, num:\n");
    JdugeByteOrder(&num);
    printf("\n");
    
    num = 0x12345678;
    int res = ExchangeByteOrder(num);
    printf("res:\n");
    JdugeByteOrder(&res);
    printf("num:\n");
    JdugeByteOrder(&num);
    printf("\n");

    res = swapInt32(num);
    printf("res:\n");
    JdugeByteOrder(&res);

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

大端小端和C实现大小端字节序的转化 的相关文章

  • 单片机中断

    蓝桥杯单片机之中断 1 中断含义及过程 中断是指CPU在处理A事情时 xff0c 发现B请求CPU立刻去处理 xff08 中断发生 xff09 xff0c 于是CPU去处理B xff08 中断服务 xff09 xff0c 处理完B后又再次回
  • AprilTag的使用、相关问题及解决方法

    使用棋盘格标定相机 安装标定功能包 span class token function sudo span span class token function apt get span span class token function i
  • 对接海康综合安防管理平台经验总结

    前言 xff1a 因业务需要对接海康威视的综合安防管理平台获得下属所管理的摄像头 xff0c 根据摄像头code获得监控视频流信息 1 详情可以浏览海康开放平台 xff0c 在官网上有对应的接入指南以及开放的API接口 前提是本地已部署了海
  • 【环境配置】Visual Studio opencv配置

    需求 在Visual Studio环境中编写C 43 43 代码 xff0c 同时可以调用OpenCV的相关代码 1 安装OpenCV 访问 opencv 官网下载对应平台的库文件 注意 xff1a Visual Studio和OpenCV
  • MySQL常见用法

    文章目录 一 时间类1 1 DATE SUB 函数1 2 NOW CURDATE CURTIME DATE 函数1 3 实战 二 统计类三 字符类3 1 LOCATE 函数3 2 concat 函数3 3 concat ws 函数3 4 g
  • 牢记公式,ardupilot EKF2就是纸老虎(四)!

    版权声明 xff1a 本文为博主原创文章 xff0c 转载请附上博文链接 xff01 四 一睹EKF2芳容 因为篇幅过长 xff0c 写的一些公式会乱码 xff0c 没办法只能把 牢记公式 xff0c ardupilot EKF2就是纸老虎
  • Java Optional使用

    文章目录 Optional一 Optional 简介二 创建 Optional 实例2 1 empty 方法2 2 of 方法2 3 ofNullable 方法 三 Optional的使用3 1 访问 Optional 对象的值3 1 1
  • 正则表达式:基础详解以及在Java中的使用

    文章目录 一 正则表达式1 1 正则表达式中的特殊字符1 2 正则表达式所支持的合法字符1 3 方括号表达式1 4 边界匹配符1 5 三种模式的数量表示符 二 应用2 1 String 类2 2 Pattern 类和 Matcher 类 一
  • Python学习:关键字global和nonlocal的用法说明

    一 global global关键字用来在函数或其他局部作用域中使用全局变量 1 1 如果局部要对全局变量修改 xff0c 而不使用global关键字 count 61 0 def global test count 43 61 1 pri
  • Python:flask框架下前后端的数据交互

    文章目录 前提 一 前端发送数据 xff0c 后端接受数据1 1 路由传参数 数据 1 2 表单提交 二 后端发送数据 xff0c 前端接受数据 前提 后端 xff1a python 的 flask 框架 前端 xff1a html css
  • Python关于None的报错:'NoneType' object is not iterable和cannot unpack non-iterable NoneType object

    文章目录 一 TypeError 39 NoneType 39 object is not iterable xff08 类型错误 xff1a 39 NoneType 39 对象不是可迭代的 xff09 二 TypeError cannot
  • Git:合并分支----git merge命令应用的三种情景

    文章目录 一 git merge 命令应用的三种情景1 1 快进 无冲突 1 2 非 快进 xff0c 修改不同文件 无冲突 1 3 非 快进 xff0c 修改相同文件 有冲突 一 git merge 命令应用的三种情景 1 1 快进 无冲
  • Git:远程分支----git fetch命令的使用

    git fetch 命令的使用 从远程主机克隆 Git 的 clone 命令会为你自动将远程主机命名为 origin xff0c 拉取它的所有数据 xff0c 创建一个指向它的 master 分支的指针 xff0c 并且在本地将其命名为 o
  • Git:移除文件----git rm命令的使用

    文章目录 一 git rm 命令使用1 1 rm 命令1 2 git rm 命令1 3 git rm f 命令1 4 git rm cached 命令 一 git rm 命令使用 Git 本地数据管理 xff0c 大概可以分为三个区 xff
  • 【OpenMv小车】OpenMv追小球的小车之pid调用

    pid py gt gt https github com wagnerc4 flight controller blob master pid py openmv 官网 xff1a http book openmv cc project
  • 【深入理解C++】函数模板作为成员函数

    文章目录 1 普通类的成员函数模板2 类模板的成员函数模板 1 普通类的成员函数模板 不管是普通类还是类模板 xff0c 它们的成员函数都可以是函数模板 xff0c 称为成员函数模板 xff0c 但不可以是虚函数 xff0c 否则编译器报错
  • QGroundControl开发之使用自定义mavlink

    工具 对QGC进行二次开发时 xff0c 常常会遇到想使用自定义mavlink的情况 xff0c 但不像APM那样编译命令会根据xml文件自动生成mavlink协议 QGC似乎不能自动生成mavlink协议 xff08 之前试过似乎不能自动
  • 字符串连接 (c语言)

    题目描述 将给定的字符串连接起来 书中的算法描述如下 xff1a 图 xff1a 字符串连接算法 输入描述 三对字符串 xff0c 每对字符串占一行 xff0c 用空格隔开 每个字符串只包含数字和英文字母大小写且长度不超过100 输出描述
  • STM32—UART中断收发 Day4

    软件 xff1a STM32CubeMX xff0c MDK ARM 硬件 xff1a 蓝桥杯物联网Lora开发板 xff0c 板载芯片STM32L071 一 STM32CubeMX配置 1 先在连接 xff08 Connectivity
  • 虚拟机出现command XXX is available in /bin/ls问题

    问题 xff1a 使用本地的shell命令时候 The command could not be located because 39 usr bin bin 39 is not included in the PATH environme

随机推荐