C语言:将四个八位无符号数据拼接成32位的float数据

server/2025/2/12 1:53:16/

目录

方法一:使用 union

解释

方法二:使用 memcpy

解释

方法三:直接指针类型转换(不推荐)

综合推荐

使用 union 方法

注意事项

验证代码


在 STM32H7 这样的嵌入式系统中,将四个 8 位无符号数据(uint8_t)拼接成一个 32 位的 float 数据,通常需要考虑字节顺序(小端大端)。STM32 默认使用小端(Little Endian)存储方式,即最低有效字节(LSB)存储在低地址,高位在高地址。

以下是几种实现方法,确保在拼接时正确处理字节顺序:

方法一:使用 union

union 允许不同类型的数据共享同一块内存区域。通过 union,可以将四个字节赋值给 uint8_t 数组,然后直接读取为 float 类型。

#include <stdint.h>
#include <stdio.h>// 定义一个联合体,包含一个 float 和一个 4 字节的数组
typedef union {float f;uint8_t bytes[4];
} FloatUnion;// 函数:将四个字节拼接成 float
float bytesToFloat(uint8_t b0, uint8_t b1, uint8_t b2, uint8_t b3) {FloatUnion fu;fu.bytes[0] = b0; // 低字节fu.bytes[1] = b1;fu.bytes[2] = b2;fu.bytes[3] = b3; // 高字节return fu.f;
}int main(void) {uint8_t byte0 = 0x00;uint8_t byte1 = 0x00;uint8_t byte2 = 0x80;uint8_t byte3 = 0x3F; // 代表 float 1.0 的 IEEE 754 编码float result = bytesToFloat(byte0, byte1, byte2, byte3);printf("Float value: %f\n", result); // 输出应为 1.000000return 0;
}

输出:

Float value: 1.000000

解释

  • 联合体 FloatUnion:包含一个 float 和一个 uint8_t 数组,二者共享同一内存。
  • 函数 bytesToFloat:将四个字节依次赋值给 bytes 数组,然后通过 fu.f 获取对应的 float 值。
  • 字节顺序:假设输入字节按小端顺序(即最低有效字节在前),上述代码会正确地将其转换为 float

方法二:使用 memcpy

memcpy 可以安全地将字节数据复制到 float 类型的变量中,避免了潜在的严格别名规则(Strict Aliasing Rule)问题。

#include <stdint.h>
#include <stdio.h>
#include <string.h>// 函数:将四个字节拼接成 float
float bytesToFloat(uint8_t b0, uint8_t b1, uint8_t b2, uint8_t b3) {uint32_t temp = ((uint32_t)b3 << 24) | ((uint32_t)b2 << 16) | ((uint32_t)b1 << 8) | b0;float f;memcpy(&f, &temp, sizeof(f));return f;
}int main(void) {uint8_t byte0 = 0x00;uint8_t byte1 = 0x00;uint8_t byte2 = 0x80;uint8_t byte3 = 0x3F; // 代表 float 1.0 的 IEEE 754 编码float result = bytesToFloat(byte0, byte1, byte2, byte3);printf("Float value: %f\n", result); // 输出应为 1.000000return 0;
}

输出:

Float value: 1.000000

解释

  • 拼接字节:将四个字节按小端顺序拼接成一个 32 位无符号整数 temp
  • memcpy:将 temp 的内容复制到 float 变量 f 中。
  • 优点:避免了通过指针类型转换可能引发的未定义行为。

方法三:直接指针类型转换(不推荐)

虽然可以通过指针类型转换实现,但这种方法可能违反 C 语言的严格别名规则,导致未定义行为。建议优先使用 unionmemcpy

#include <stdint.h>
#include <stdio.h>// 函数:将四个字节拼接成 float
float bytesToFloat(uint8_t b0, uint8_t b1, uint8_t b2, uint8_t b3) {uint32_t temp = ((uint32_t)b3 << 24) | ((uint32_t)b2 << 16) | ((uint32_t)b1 << 8) | b0;return *(float*)&temp; // 可能导致未定义行为
}int main(void) {uint8_t byte0 = 0x00;uint8_t byte1 = 0x00;uint8_t byte2 = 0x80;uint8_t byte3 = 0x3F; // 代表 float 1.0 的 IEEE 754 编码float result = bytesToFloat(byte0, byte1, byte2, byte3);printf("Float value: %f\n", result); // 输出应为 1.000000return 0;
}

注意:这种方法不推荐使用,因为它可能在某些编译器或优化级别下引发问题。

综合推荐

使用 union 方法

union 方法简洁且安全,适合嵌入式系统中对性能和资源有严格要求的场景。以下是完整示例:

#include <stdint.h>
#include <stdio.h>// 定义联合体
typedef union {float f;uint8_t bytes[4];
} FloatUnion;// 将四个字节拼接成 float
float bytesToFloat(uint8_t b0, uint8_t b1, uint8_t b2, uint8_t b3) {FloatUnion fu;fu.bytes[0] = b0; // LSBfu.bytes[1] = b1;fu.bytes[2] = b2;fu.bytes[3] = b3; // MSBreturn fu.f;
}int main(void) {// 示例字节,表示 float 1.0uint8_t byte0 = 0x00;uint8_t byte1 = 0x00;uint8_t byte2 = 0x80;uint8_t byte3 = 0x3F;float result = bytesToFloat(byte0, byte1, byte2, byte3);printf("Float value: %f\n", result); // 应输出 1.000000return 0;
}

注意事项

  1. 字节顺序:确保输入字节按 STM32 的小端顺序排列。如果字节顺序不同,需要调整字节的赋值顺序。
  2. 浮点数表示:确保输入字节正确表示 IEEE 754 浮点数格式。
  3. 内存对齐:在嵌入式系统中,访问未对齐的内存可能导致性能下降或异常。使用 unionmemcpy 通常能避免此问题。

验证代码

编译并运行上述代码,可以验证拼接结果是否正确。例如,四个字节 0x00, 0x00, 0x80, 0x3F 应对应 float1.0

Float value: 1.000000

这样,你就成功地将四个 8 位无符号数据拼接成一个 32 位的 float 数据了。


http://www.ppmy.cn/server/166407.html

相关文章

国内知名Deepseek培训师培训讲师唐兴通老师讲授AI人工智能大模型实践应用

课程名称 《Deepseek人工智能大模型实践应用》 课程目标 全面了解Deepseek人工智能大模型的技术原理、功能特点及应用场景。 熟练掌握Deepseek大模型的提示词工程技巧&#xff0c;能够编写高质量的提示词。 掌握Deepseek大模型在办公、营销等领域的应用方法&#xff0c;提升…

无人机GPS模块概述!

一、GPS模块 原理&#xff1a;GPS模块通过接收来自卫星系统的信号&#xff0c;计算出无人机当前的位置、速度和时间等信息。它主要由接收天线、接收器、信号处理器和电源等组成。接收天线接收来自卫星的GPS信号&#xff0c;接收器将信号转换为数字信号并传输给信号处理器&…

架构师成长(四)之深入理解 JVM 虚拟机栈

一、虚拟机栈概述 Java 虚拟机栈&#xff08;Java Virtual Machine Stack&#xff09;是 Java 虚拟机运行时数据区的重要组成部分之一&#xff0c;它与线程紧密相关。每个 Java 线程在创建时都会分配一个独立的虚拟机栈&#xff0c;其生命周期与线程相同。 虚拟机栈的主要作用…

海思的一站式集成环境Hispark Studio更新了

HiSpark Studio是海思提供的面向智能设备开发者提供一站式集成开发环境&#xff0c;支持代码编辑、编译、烧录和调试等功能。我以前在评测星闪芯片的时候用过&#xff0c;当时写了篇博客&#xff1a;【星闪开发连载】WS63E开发板Windows环境的构建_hispark studio-CSDN博客。那…

DeepSeek与Vue.js组件开发:解锁AI与前端开发的融合密码

前言&#xff1a;哈喽&#xff0c;大家好&#xff0c;今天给大家分享一篇文章&#xff01;并提供具体代码帮助大家深入理解&#xff0c;彻底掌握&#xff01;创作不易&#xff0c;如果能帮助到大家或者给大家一些灵感和启发&#xff0c;欢迎收藏关注哦 &#x1f495; 目录 Deep…

java Jvm 双亲委派模型

一句话总结&#xff1a;类加载器&#xff08;class loader&#xff09;用来加载 Java 类到 Java 虚拟机中。 官方&#xff1a;Java类加载器&#xff08;英语&#xff1a;Java Classloader&#xff09;是Java运行时环境&#xff08;Java Runtime Environment&#xff09;的一部…

SQL Server2019下载及安装教程

一、软件下载 SQLServer2019及SSMS管理工具下载链接&#xff1a; 百度网盘 请输入提取码 二、SQLServer2019安装 选中要安装的iso映像文件&#xff0c;右键点击装载&#xff08;有些系统可以直接双击打开&#xff0c;有些需要安装Daemon Tools软件去打开&#xff09; 找到s…

《Python语言程序设计》(2018年版)第15遍刷第1章第1题第2版。我尝试建立一个解密的办法

这个代码是不是说明&#xff0c;我附加的随机数&#xff0c;超出了ascii码的范畴&#xff0c;或者是不是超出了我机器的范畴。 text_in_M "Welcome to Python" text_char_m "Zgnerph#wp#Szujpo" # key_int [3, 2, 2, 2, 3, 3, 3, 3, 3, 1, 3, 3, 1, 1, …