【208】VS2022 C++ 32位整数和unsigned char数组之间互相转换
一、场景
在实际应用中,特别是在数据传输的时候,需要读取unsigned char数组,再转换成 32 位整数;或者把 32 位整数转换成 unsigned char数组进行写入。比如对接西门子PLC的 snap7 就是这样。32 位整数分成有符号的无符号的,我们分开讨论。
二、有符号的 32 位整数
2.1 补码的原理
原码:最高位0表示正数,1表示负数。其他位就是用二进制表示数字。
反码:正整数反码和原码相同。负整数原码最高位不变;其他位 0 变 1,1 变 0;最终结果就是负整数的反码。
补码:正整数的补码和原码相同。负整数的补码是它的反码加一。
怎么把补码转换为原码?只要对补码再做一次补码操作就行。
计算机的整数是用补码储存的。这样做的好处是用加法运算替代减法运算。任何加减运算只需要让两个数字的补码相加就行了。
我可以利用这个特性,做到 unsigned char 数组和有符号32位整数互相转换。
2.2 有符号32位整数转换成 unsigned char 数组
执行代码
int a = -1550458175;
unsigned char c = a;
这段代码中,unsigned char 类型的变量 c 是存放了 int 类型变量 a 的低 8 位二进制补码。利用这个特点,对 int 类型的变量 a 分别不右移、右移 8 位、右移 16 位、右移 24 位,然后分别赋值给四个 unsigned char 类型的变量,那么这四个变量可以获取从低到高 4 个字节(1 字节等于 8 位)的补码数据。具体实现方式建议读者看后面 int ucharArrToInt(const unsigned char* const inArr, const int inArrSize, const int inStart, int* outResult)
函数。
2.3 unsigned char 数组转换成有符号32位整数
声明四个 int 变量 data_1、data_2、data_3 和 data_4,初始值是 0.
data_1 赋值成 unsigned char 数组第 0 个元素,然后左移 24 位。
data_2 赋值成 unsigned char 数组第 1 个元素,然后左移 16 位。
data_3 赋值成 unsigned char 数组第 2 个元素,然后左移 8 位。
data_4 赋值成 unsigned char 数组第 3 个元素。
data_1、data_2、data_3 和 data_4 四个整数相加。
如果原来的整数是正数或者是零,这么干完全没问题。
如果原来的整数是负数呢?其实也没有问题。虽然这种做法会让 data_1 是负数,data_2、data_3、data_4 是正数,但是补码的运算方式是减法当加法运算,这四个 int 类型变量的补码会只在自己对应二进制位置有值,其他的地方都是零。即这四个数字的补码互不影响,最后相加的结果就是原来有符号 32 位整数的补码。
下面是测试的代码
#include <stdio.h>
#include <stdlib.h>
#include <random>#define ARR_SIZE 256// 把有符号32位整数转换成 unsigned char 数组
// inNum 输入参数,要转换的有符号32位整数
// inArrSize 输入参数,输出参数outArr的长度
// inStart 输入参数,输出参数outArr 从第几个元素开始写入转换后的数据。
// outArr 输出参数,保存转换后的数组内容。
int intToUcharArr(const int inNum, const int inArrSize, const int inStart, unsigned char* const outArr) {if (inArrSize - inStart < 4) {return -1;}outArr[inStart + 3] = inNum;outArr[inStart + 2] = inNum >> 8;outArr[inStart + 1] = inNum >> 16; // 8 * 2outArr[inStart] = inNum >> 24; // 8 * 3return 0;
}// unsigned char 数组转换成有符号32位整数
// inArr 输入参数,unsigned char 数组。
// inArrSize 输入参数,数组inArr的长度。
// inStart 输入参数,表示从哪个 inArr 的元素开始,读取四个元素转换成int
// outResult 输出参数,转换后的结果
// 返回:0表示正常,其他值表示出错。
int ucharArrToInt(const unsigned char* const inArr, const int inArrSize, const int inStart, int* outResult) {if (inArrSize - inStart < 4) {return -1;}unsigned char c1 = inArr[inStart];unsigned char c2 = inArr[inStart + 1];unsigned char c3 = inArr[inStart + 2];unsigned char c4 = inArr[inStart + 3];int data_1 = 0;int data_2 = 0;int data_3 = 0;int data_4 = 0;data_1 = c1;data_1 = data_1 << 24; // 8 * 3data_2 = c2;data_2 = data_2 << 16; // 8 * 2data_3 = c3;data_3 = data_3 << 8;data_4 = c4;(*outResult) = data_1 + data_2 + data_3 + data_4;return 0;
}// 生成 INT_MIN 到 INT_MAX 随机数,包含 INT_MIN 和 INT_MAX
int genRandom() {// 使用随机设备作为种子std::random_device rd;// 使用 Mersenne Twister 引擎std::mt19937 gen(rd());// 定义分布范围 [0, 255]std::uniform_int_distribution<> distr(INT_MIN, INT_MAX);// 生成并输出随机数int result = distr(gen);return result;
}int main(int argc, char** argv) {system("color 02");printf("argc=%d\n", argc);int ret = -1;// 生成随机数int num = genRandom();//int num = INT_MIN;printf("num = %d\n", num);// 先把随机32位整数转换成 unsigned char 数组,再转换回 32 位整数unsigned char arr[ARR_SIZE];ret = intToUcharArr(num, ARR_SIZE, 0, arr);if (0 != ret) {printf("intToUcharArr error. ret=%d\n", ret);return -1;}int n2 = 0;ret = ucharArrToInt(arr, ARR_SIZE, 0, &n2);if (0 != ret) {printf("ucharArrToInt error. ret=%d\n", ret);return -1;}printf("n2 = %d\n", n2);if (num == n2) {printf("true\n");}else {printf("false\n");}return 0;
}
三、无符号的 32 位整数
计算机中正整数的补码和原码相同,无符号32位整数和 unsigned char 数组的转换方式和有符号的一样。只是需要注意需要改成 unsigned int
类型。
#include <stdio.h>
#include <stdlib.h>
#include <random>#define ARR_SIZE 256// 把有符号32位整数转换成 unsigned char 数组
// inNum 输入参数,要转换的有符号32位整数
// inArrSize 输入参数,输出参数outArr的长度
// inStart 输入参数,输出参数outArr 从第几个元素开始写入转换后的数据。
// outArr 输出参数,保存转换后的数组内容。
int intToUcharArr(const unsigned int inNum, const int inArrSize, const int inStart, unsigned char* const outArr) {if (inArrSize - inStart < 4) {return -1;}outArr[inStart + 3] = inNum;outArr[inStart + 2] = inNum >> 8;outArr[inStart + 1] = inNum >> 16; // 8 * 2outArr[inStart] = inNum >> 24; // 8 * 3return 0;
}// unsigned char 数组转换成有符号32位整数
// inArr 输入参数,unsigned char 数组。
// inArrSize 输入参数,数组inArr的长度。
// inStart 输入参数,表示从哪个 inArr 的元素开始,读取四个元素转换成int
// outResult 输出参数,转换后的结果
// 返回:0表示正常,其他值表示出错。
int ucharArrToInt(const unsigned char* const inArr, const int inArrSize, const int inStart, unsigned int* outResult) {if (inArrSize - inStart < 4) {return -1;}unsigned char c1 = inArr[inStart];unsigned char c2 = inArr[inStart + 1];unsigned char c3 = inArr[inStart + 2];unsigned char c4 = inArr[inStart + 3];unsigned int data_1 = 0;unsigned int data_2 = 0;unsigned int data_3 = 0;unsigned int data_4 = 0;data_1 = c1;data_1 = data_1 << 24; // 8 * 3data_2 = c2;data_2 = data_2 << 16; // 8 * 2data_3 = c3;data_3 = data_3 << 8;data_4 = c4;(*outResult) = data_1 + data_2 + data_3 + data_4;return 0;
}// 生成 INT_MIN 到 INT_MAX 随机数,包含 INT_MIN 和 INT_MAX
unsigned int genRandom() {// 使用随机设备作为种子std::random_device rd;// 使用 Mersenne Twister 引擎std::mt19937 gen(rd());// 定义分布范围 [INT_MIN, INT_MAX]std::uniform_int_distribution<> distr(0, INT_MAX);// 生成并输出随机数unsigned int result = distr(gen);return result;
}int main(int argc, char** argv) {system("color 02");printf("argc=%d\n", argc);int ret = -1;// 生成随机数unsigned int num = genRandom();//int num = INT_MIN;printf("num = %d\n", num);// 先把随机32位整数转换成 unsigned char 数组,再转换回 32 位整数unsigned char arr[ARR_SIZE];ret = intToUcharArr(num, ARR_SIZE, 0, arr);if (0 != ret) {printf("intToUcharArr error. ret=%d\n", ret);return -1;}unsigned int n2 = 0;ret = ucharArrToInt(arr, ARR_SIZE, 0, &n2);if (0 != ret) {printf("ucharArrToInt error. ret=%d\n", ret);return -1;}printf("n2 = %d\n", n2);if (num == n2) {printf("true\n");}else {printf("false\n");}return 0;
}
相关文章:
【208】VS2022 C++ 32位整数和unsigned char数组之间互相转换
一、场景 在实际应用中,特别是在数据传输的时候,需要读取unsigned char数组,再转换成 32 位整数;或者把 32 位整数转换成 unsigned char数组进行写入。比如对接西门子PLC的 snap7 就是这样。32 位整数分成有符号的无符号的&#…...
数据库技术
InnoDB是什么?MySQL 和 InnoDB的关系是什么? InnoDB是MySQL数据库系统中最重要且默认的存储引擎。MySQL采用插件式存储引擎架构,作为数据库管理系统本身不直接处理数据存储,而是通过存储引擎接口与InnoDB等引擎交互。InnoDB作为M…...

深入浅出:Oracle 数据库 SQL 执行计划查看详解(1)——基础概念与查看方式
背景 在当今的软件开发领域,尽管主流开发模式往往倾向于采用单表模式,力图尽可能地减少表之间的连接操作,以期达到提高数据处理效率、简化应用逻辑等目的。然而,对于那些已经上线运行多年的运维老系统而言,它们内部往…...

前端HTML contenteditable 属性使用指南
什么是 contenteditable? HTML5 提供的全局属性,使元素内容可编辑类似于简易富文本编辑器兼容性 支持所有现代浏览器(Chrome、Firefox、Safari、Edge) 移动端(iOS/Android)部分键盘行为需测试 &l…...

自动化采集脚本与隧道IP防封设计
最近群里讨论问如何编写一个自动化采集脚本,要求使用隧道IP(代理IP池)来防止IP被封。这样的脚本通常用于爬虫或数据采集任务,其中目标网站可能会因为频繁的请求而封禁IP。对于这些我还是有些经验的。 核心思路: 1、使…...

【设计模式-4.7】行为型——备忘录模式
说明:本文介绍行为型设计模式之一的备忘录模式 定义 备忘录模式(Memento Pattern)又叫作快照模式(Snapshot Pattern)或令牌模式(Token Pattern)指在不破坏封装的前提下,捕获一个对…...

docker离线镜像下载
背景介绍 在某些网络受限的环境中,直接从Docker Hub或其他在线仓库拉取镜像可能会遇到困难。为了在这种情况下也能顺利使用Docker镜像,我们可以提前下载好所需的镜像,并通过离线方式分发和使用。 当前镜像有:python-3.8-slim.ta…...

Vert.x学习笔记-Verticle原理解析
Vert.x学习笔记 一、设计理念:事件驱动的组件化模型二、生命周期管理三、部署方式与策略四、通信机制:事件总线(Event Bus)五、底层实现原理六、典型应用场景七、Verticle与EventLoop的关系1、核心关系:一对一绑定与线…...
Cobra CLI 工具使用指南:构建 Go 语言命令行应用的完整教程
Cobra CLI 工具使用指南:构建 Go 语言命令行应用的完整教程 在 Go 语言开发中,构建功能强大的命令行界面(CLI)应用是常见需求。Cobra 作为 Go 生态中最受欢迎的 CLI 库,凭借其灵活的设计和丰富的功能,成为…...

jQuery和CSS3卡片列表布局特效
这是一款jQuery和CSS3卡片列表布局特效。该卡片布局使用owl.carousel.js来制作轮播效果,使用简单的css代码来制作卡片布局,整体效果时尚大方。 预览 下载 使用方法 在页面最后引入jquery和owl.carousel.js相关文件。 <link rel"stylesheet&qu…...

不连网也能跑大模型?
一、这是个什么 App? 你有没有想过,不用连网,你的手机也能像 ChatGPT 那样生成文字、识别图片、甚至回答复杂问题?Google 最近悄悄发布了一个实验性 Android 应用——AI Edge Gallery,就是为此而生的。 这个应用不在…...

强化学习鱼书(10)——更多深度强化学习的算法
:是否使用环境模型(状态迁移函数P(s’|s,a)和奖 励函数r(s,a,V))。不使用环境模型的方法叫作无模型(model-free)的方法,使用环境模型的方法叫作有模型(model-based&#…...

K8S上使用helm部署 Prometheus + Grafana
一、使用 Helm 安装 Prometheus 1. 配置源 地址:prometheus 27.19.0 prometheus/prometheus-community # 添加repo $ helm repo add prometheus-community https://prometheus-community.github.io/helm-charts "prometheus-community" has been added…...
十四、【测试执行篇】让测试跑起来:API 接口测试执行器设计与实现 (后端执行逻辑)
@[TOC](【测试执行篇】让测试跑起来:API 接口测试执行器设计与实现 (后端执行逻辑)) 前言 测试执行是测试平台的核心价值所在。一个好的测试执行器需要能够: 准确解析测试用例: 正确理解用例中定义的请求参数和断言条件。可靠地发送请求: 模拟真实的客户端行为与被测 API…...

Java面试八股--07-项目篇
致谢:2025年 Java 面试八股文(20w字)_java面试八股文-CSDN博客 目录 1、介绍一下最近做的项目 1.1 项目背景: 1.2 项目功能 1.3 技术栈 1.4自己负责的功能模块 1.5项目介绍参考: 1.6整体业务介绍: 1.8后台管理系统功能: 1.8.1后台主页: 1.8.2 商品模块: 1.8…...

MCP架构全解析:从核心原理到企业级实践
💝💝💝欢迎莅临我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:「storms…...

从0到1认识EFK
一、ES集群部署 操作系统Ubuntu22.04LTS/主机名IP地址主机配置elk9110.0.0.91/244Core8GB100GB磁盘elk9210.0.0.92/244Core8GB100GB磁盘elk9310.0.0.93/244Core8GB100GB磁盘 1. 什么是ElasticStack? # 官网 https://www.elastic.co/ ElasticStack早期名称为elk。 elk分别…...
快速了解GO+ElasticSearch
更多个人笔记见: (注意点击“继续”,而不是“发现新项目”) github个人笔记仓库 https://github.com/ZHLOVEYY/IT_note gitee 个人笔记仓库 https://gitee.com/harryhack/it_note 个人学习,学习过程中还会不断补充&…...

定制开发开源AI智能名片驱动下的海报工厂S2B2C商城小程序运营策略——基于社群口碑传播与子市场细分的实证研究
摘要 本文聚焦“定制开发开源AI智能名片S2B2C商城小程序”技术与海报工厂业务的融合实践,探讨其如何通过风格化海报矩阵的精细化开发、AI技术驱动的用户体验升级,以及S2B2C模式下的社群裂变机制,实现“工具功能-社交传播-商业变现”的生态…...

【Unity开发】控制手机移动端的震动
🐾 个人主页 🐾 阿松爱睡觉,横竖醒不来 🏅你可以不屠龙,但不能不磨剑🗡 目录 一、前言二、Unity的Handheld.Vibrate()三、调用Android原生代码四、NiceVibrations插件五、DeviceVibration插件六、控制游戏手…...
JAVA中的注解和泛型
目录 JAVA注解介绍 概念 注解的本质 4种标准元注解 自定义注解 泛型介绍 泛型的定义 JAVA泛型 泛型方法( ) 泛型类( ) 类型通配符 类型擦除 JAVA注解介绍 概念 注解是 JDK 5.0 引入的一种元数据机制,用来对代码进行标注。它不会影…...

Cesium快速入门到精通系列教程二:添加地形与添加自定义地形、相机控制
一、添加地形与添加自定义地形 在 Cesium 1.93 中添加地形可以通过配置terrainProvider实现。Cesium 支持多种地形数据源,包括 Cesium Ion 提供的全球地形、自定义地形服务以及开源地形数据。下面介绍几种常见的添加地形的方法: 使用 Cesium Ion 全球地…...
汽车零配件---ecu开发工厂学习
ecu成品制作工艺流程 一、PCB 设计与制作(打板) 工艺流程步骤 需求分析与电路设计 根据 ECU 功能(如发动机控制、变速箱控制)确定所需芯片(如 MCU、传感器接口芯片)、外围电路(如电源、通信接…...

python学习打卡day43
DAY 43 复习日 作业: kaggle找到一个图像数据集,用cnn网络进行训练并且用grad-cam做可视化 浙大疏锦行 数据集使用猫狗数据集,训练集中包含猫图像4000张、狗图像4005张。测试集包含猫图像1012张,狗图像1013张。以下是数据集的下…...

Microsoft Word使用技巧分享(本科毕业论文版)
小铃铛最近终于完成了毕业答辩后空闲下来了,但是由于学校没有给出准确地参考模板,相信诸位朋友们也在调整排版时感到头疼,接下来小铃铛就自己使用到的一些排版技巧分享给大家。 注:以下某些设置是根据哈尔滨工业大学(威…...

windows安装多个版本composer
一、需求场景 公司存在多个项目,有的项目比较老,需要composer 1.X版本才能使用 新的项目又需要composer 2.X版本才能使用 所以需要同时安装多个版本的composer二、下载多个版本composer #composer官网 https://getcomposer.org/download/三、放到指定目…...

【办公类-22-05】20250601Python模拟点击鼠标上传CSDN12篇
、 背景需求: 每周为了获取流量券,每天上传2篇,获得1500流量券,每周共上传12篇,才能获得3000和500的券。之前我用UIBOT模拟上传12篇。 【办公类-22-04】20240418 UIBOT模拟上传每天两篇,获取流量券,并删除内容_csdn 每日任务流量券-CSDN博客文章浏览阅读863次,点赞18…...

贪心算法应用:边着色问题详解
贪心算法应用:边着色问题详解 贪心算法是一种在每一步选择中都采取当前状态下最优的选择,从而希望导致结果是全局最优的算法策略。边着色问题是图论中的一个经典问题,贪心算法可以有效地解决它。下面我将从基础概念到具体实现,全…...
【蓝桥杯】包子凑数
包子凑数 题目描述 小明几乎每天早晨都会在一家包子铺吃早餐。他发现这家包子铺有 NN 种蒸笼,其中第 ii 种蒸笼恰好能放 AiAi 个包子。每种蒸笼都有非常多笼,可以认为是无限笼。 每当有顾客想买 XX 个包子,卖包子的大叔就会迅速选出若干…...

ck-editor5的研究 (2):对 CKEditor5 进行设计,并封装成一个可用的 vue 组件
前言 在上一篇文章中—— ck-editor5的研究(1):快速把 CKEditor5 集成到 nuxt 中 ,我仅仅是把 ckeditor5 引入到了 nuxt 中,功能还不算通用。 这一篇内容将会对其进行设计,并封装成可复用的 vue 组件&…...