C语言数据结构笔记3:Union联合体+结构体取8位Bool量

news2025/6/7 16:09:25

本文衔接上文要求,新增8位bool量的获取方式。

目录

问题提出:

Union联合体+struct结构体(方式1):

Union联合体+struct结构体(方式2):

BYTE方式读取:


问题提出:

在STM32单片机的编程中,无法定义Bool或者bit类型

但有时候,比如modbus通信时,需要把bool量八个八个地组合读取,少于8个的部分填充0

Union联合体+struct结构体(方式1):

这里是考虑到超过8位的使用场景,因此定义了超过3字节的定义方式

这种方式适合那种喜欢一个一个列出所有寄存器位名称的情况。


#define BITS_PER_BYTE 8
#define BYTES_FOR_BITS 3  //
 
// 定义3字节的位字段结构
typedef union {
    uint8_t bytes[BYTES_FOR_BITS];  // 整个字节数组访问
    struct {
        // 每个字节单独定义位字段
        struct {
            uint8_t b0 : 1;
            uint8_t b1 : 1;
            uint8_t b2 : 1;
            uint8_t b3 : 1;
            uint8_t b4 : 1;
            uint8_t b5 : 1;
            uint8_t b6 : 1;
            uint8_t b7 : 1;
        } byte0;
        struct {
            uint8_t b0 : 1;
            uint8_t b1 : 1;
            uint8_t b2 : 1;
            uint8_t b3 : 1;
            uint8_t b4 : 1;
            uint8_t b5 : 1;
            uint8_t b6 : 1;
            uint8_t b7 : 1;
        } byte1;
        struct {
            uint8_t b0 : 1;
            uint8_t b1 : 1;
            uint8_t b2 : 1;
            uint8_t b3 : 1;
            uint8_t b4 : 1;
            uint8_t b5 : 1;
            uint8_t b6 : 1;
            uint8_t b7 : 1;
        } byte2;
    } bits;
} LargeBitField;
#include <stdio.h>

typedef unsigned char uint8_t;
typedef unsigned short int    uint16_t;
typedef signed short int      int16_t;

#pragma pack(push, 1) //:将结构体的对齐方式设置为 1 字节,并将当前对齐设置保存到堆栈中。

//0x03e8 - 0x03ee
typedef struct  ABC_regs1
{
    uint16_t  A1;
    uint16_t  B1;
    int16_t   C1;
    int16_t   D1;
    uint16_t  E1;
    int16_t   F1;
    int16_t   G1;
}ABC_regs_1;

//0x177B - 0x1781
typedef struct  ABC_regs2
{
    uint16_t  A2;
    uint16_t  B2;
    int16_t   C2;
    int16_t   D2;
    uint16_t  E2;
    int16_t   F2;
    int16_t   G2;
}ABC_regs_2;

#define BITS_PER_BYTE 8
#define BYTES_FOR_BITS 3  //
 
// 定义15字节的位字段结构
typedef union {
    uint8_t bytes[BYTES_FOR_BITS];  // 整个字节数组访问
    struct {
        // 每个字节单独定义位字段
        struct {
            uint8_t b0 : 1;
            uint8_t b1 : 1;
            uint8_t b2 : 1;
            uint8_t b3 : 1;
            uint8_t b4 : 1;
            uint8_t b5 : 1;
            uint8_t b6 : 1;
            uint8_t b7 : 1;
        } byte0;
        struct {
            uint8_t b0 : 1;
            uint8_t b1 : 1;
            uint8_t b2 : 1;
            uint8_t b3 : 1;
            uint8_t b4 : 1;
            uint8_t b5 : 1;
            uint8_t b6 : 1;
            uint8_t b7 : 1;
        } byte1;
        struct {
            uint8_t b0 : 1;
            uint8_t b1 : 1;
            uint8_t b2 : 1;
            uint8_t b3 : 1;
            uint8_t b4 : 1;
            uint8_t b5 : 1;
            uint8_t b6 : 1;
            uint8_t b7 : 1;
        } byte2;
    } bits;
} LargeBitField;


typedef struct  Letter_regs
{
    ABC_regs_1 ABC1;  //0x03e8 - 0x03f1 //7成员 14字节 //偏移量 0x00- 0x0c
    ABC_regs_2 ABC2;  //0x177B - 0x1781 //7成员 14字节 
    //BOOL_1     Bool1; //
    LargeBitField Bytes;
}letter_regs;



int main(void)
{
    letter_regs reg;


    // 设置位
    reg.Bytes.bits.byte0.b0 = 1;  // 设置byte0的第0位为1
    reg.Bytes.bits.byte1.b7 = 1;  // 设置byte1的第7位为1
 
    // 读取位
    uint8_t bit0 = reg.Bytes.bits.byte0.b0;
    uint8_t bit7 = reg.Bytes.bits.byte1.b7;
 
    printf("Bit 0 of byte0: %d\n", bit0);
    printf("Bit 7 of byte1: %d\n", bit7);
 
    // 通过字节数组访问
    reg.Bytes.bytes[0] = 0x0F;  // 设置byte0为0x0F
    printf("Byte 0: 0x%02X\n", reg.Bytes.bytes[0]);


}

Union联合体+struct结构体(方式2):

这种方式不一个一个列出寄存器名称,直接通过地址偏移操作:

#include <stdio.h>

typedef unsigned char uint8_t;
typedef unsigned short int    uint16_t;
typedef signed short int      int16_t;

#pragma pack(push, 1) //:将结构体的对齐方式设置为 1 字节,并将当前对齐设置保存到堆栈中。

//0x03e8 - 0x03ee
typedef struct  ABC_regs1
{
    uint16_t  A1;
    uint16_t  B1;
    int16_t   C1;
    int16_t   D1;
    uint16_t  E1;
    int16_t   F1;
    int16_t   G1;
}ABC_regs_1;

//0x177B - 0x1781
typedef struct  ABC_regs2
{
    uint16_t  A2;
    uint16_t  B2;
    int16_t   C2;
    int16_t   D2;
    uint16_t  E2;
    int16_t   F2;
    int16_t   G2;
}ABC_regs_2;

// 定义字节的位字段结构
typedef union {
    uint8_t byte;  // 整个字节数组访问
        struct {
            uint8_t b0 : 1;
            uint8_t b1 : 1;
            uint8_t b2 : 1;
            uint8_t b3 : 1;
            uint8_t b4 : 1;
            uint8_t b5 : 1;
            uint8_t b6 : 1;
            uint8_t b7 : 1;
        } bits;
}BitField;


typedef struct  Letter_regs
{
    ABC_regs_1 ABC1;  //0x03e8 - 0x03f1 //7成员 14字节 //偏移量 0x00- 0x0c
    ABC_regs_2 ABC2;  //0x177B - 0x1781 //7成员 14字节 
    BitField Bytes[10];
}letter_regs;



int main(void)
{
    letter_regs reg;
    // 通过直接赋值给联合体的字节
    reg.Bytes[0].byte = 0xA5;  // 0xA5 in hex is 10100101 in binary
 
    // 通过位域赋值
    reg.Bytes[1].bits.b0 = 1;  // Set bit 0 to 1
    reg.Bytes[1].bits.b7 = 1;  // Set bit 7 to 1
 
    // 读取并打印结果
    printf("Byte 0: 0x%02X\n", reg.Bytes[0].byte);  // 输出 0xA5
    printf("Byte 1: 0x%02X\n", reg.Bytes[1].byte);  // 输出 0x81 (因为 b7 和 b0 被设置为1)
 
}

BYTE方式读取:

#include <stdio.h>

typedef unsigned char uint8_t;
typedef unsigned short int    uint16_t;
typedef signed short int      int16_t;
#pragma pack(push, 1) //:将结构体的对齐方式设置为 1 字节,并将当前对齐设置保存到堆栈中。

//0x03e8 - 0x03ee
typedef struct  ABC_regs1
{
    uint16_t  A1;
    uint16_t  B1;
    int16_t   C1;
    int16_t   D1;
    uint16_t  E1;
    int16_t   F1;
    int16_t   G1;
}ABC_regs_1;

//0x177B - 0x1781
typedef struct  ABC_regs2
{
    uint16_t  A2;
    uint16_t  B2;
    int16_t   C2;
    int16_t   D2;
    uint16_t  E2;
    int16_t   F2;
    int16_t   G2;
}ABC_regs_2;

// 定义字节的位字段结构
typedef union {
    uint8_t byte;  // 整个字节数组访问
        struct {
            uint8_t b0 : 1;
            uint8_t b1 : 1;
            uint8_t b2 : 1;
            uint8_t b3 : 1;
            uint8_t b4 : 1;
            uint8_t b5 : 1;
            uint8_t b6 : 1;
            uint8_t b7 : 1;
        } bits;
}BitField;

typedef struct  Letter_regs
{
    ABC_regs_1 ABC1;  //0x03e8 - 0x03f1 //7成员 14字节
    ABC_regs_2 ABC2;  //0x177B - 0x1781 //7成员 14字节 
    BitField Bytes[10]; //0x0400 - 0x0450 //80 成员 
}letter_regs;

int main(void)
{
    letter_regs reg;
    // 通过直接赋值给联合体的字节
    reg.Bytes[0].byte = 0xAA;  // 0xA5 in hex is 10100101 in binary
     reg.Bytes[8].byte = 0x6A;  // 0xA5 in hex is 10100101 in binary
    unsigned char* ptr = (unsigned char*)&reg.Bytes;

    //print_struct_values(&reg);

     //联合体读8个,实际物理地址才偏移1,相对于基地址地偏移量,都一个BYTE才偏移1
     for (int j = 0; j < 10; j++) //读10个BYTE 整个联合体
    {
        unsigned char offset = j; // 计算偏移量
        uint8_t value = *(const uint8_t*)(ptr + offset);
         printf("Byte %d: 0x%02X\n",j,value);
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2401273.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SAP学习笔记 - 开发22 - 前端Fiori开发 数据绑定(Jason),Data Types(数据类型)

上一章讲了Icons&#xff08;图标&#xff09;&#xff0c;Icon Explorer。 SAP学习笔记 - 开发21 - 前端Fiori开发 Icons&#xff08;图标&#xff09;&#xff0c;Icon Explorer&#xff08;图标浏览器&#xff09;-CSDN博客 本章继续讲SAP Fiori开发的知识。 目录 1&…

网络编程之TCP编程

基于 C/S &#xff1a;客户端&#xff08;client&#xff09;/服务器端&#xff08;server&#xff09; 1.流程 2. 函数接口 所有函数所需头文件&#xff1a; #include <sys/types.h> #include <sys/socket.h> 系统定义好了用来存储网络信息的结构体 ipv4通信使…

C++进阶--C++11(04)

文章目录 C进阶--C11&#xff08;04&#xff09;lambdalambda表达式语法捕捉列表lambda的应用lambda的原理 包装器functionbind 总结结语 很高兴和大家见面&#xff0c;给生活加点impetus&#xff01;&#xff01;开启今天的编程之路&#xff01;&#xff01; 今天我们进一步c…

当AI遇上防火墙:新一代智能安全解决方案全景解析

在2025年网络安全攻防升级的背景下&#xff0c;AI与防火墙的融合正重塑安全防御体系。以下三款产品通过机器学习、行为分析等技术创新&#xff0c;为企业提供智能化主动防护&#xff1a; 1. 保旺达数据安全管控平台——AI驱动的动态治理引擎‌ 智能分类分级‌&#xff1a;基于…

Spring MVC参数绑定终极手册:单多参/对象/集合/JSON/文件上传精讲

我们通过浏览器访问不同的路径&#xff0c;就是在发送不同的请求&#xff0c;在发送请求时&#xff0c;可能会带一些参数&#xff0c;本文将介绍了Spring MVC中处理不同请求参数的多种方式 一、传递单个参数 接收单个参数&#xff0c;在Spring MVC中直接用方法中的参数就可以&…

Fluence推出“Pointless计划”:五种方式参与RWA算力资产新时代

2025年6月1日&#xff0c;去中心化算力平台 Fluence 正式宣布启动“Pointless 计划”——这是其《Fluence Vision 2026》战略中四项核心举措之一&#xff0c;旨在通过贡献驱动的积分体系&#xff0c;激励更广泛的社区参与&#xff0c;为用户带来现实世界资产&#xff08;RWA&am…

innovus: ecoAddRepeater改变hier层级解决办法

我正在「拾陆楼」和朋友们讨论有趣的话题&#xff0c;你⼀起来吧&#xff1f; 拾陆楼知识星球入口 来自星球提问: 星主&#xff0c;我在A/B/C/D/E/U0这个cell后面插入一个BUFF&#xff0c;生成的名字为A/B/C/BUFF1&#xff0c;少了D/E两个层级&#xff0c;不应该是生成A/B/C/…

华为OD机试真题——硬件产品销售方案(2025A卷:100分)Java/python/JavaScript/C++/C语言/GO六种最佳实现

2025 A卷 100分 题型 本文涵盖详细的问题分析、解题思路、代码实现、代码详解、测试用例以及综合分析; 并提供Java、python、JavaScript、C++、C语言、GO六种语言的最佳实现方式! 2025华为OD真题目录+全流程解析/备考攻略/经验分享 华为OD机试真题《硬件产品销售方案》: 目录…

传统业务对接AI-AI编程框架-Rasa的业务应用实战(1)--项目背景即学习初衷

我的初衷&#xff1a;我想学习AI。具体的方向是这样的&#xff1a;原本传统的平台业务去对接智能体。比如发票业务&#xff0c;发票的开具、审核、计税、回款等。根据用户在业务系统前台界面输入若干提示词 或者 语音输入简短语音信息&#xff0c;可以通过智能体给出需要处理的…

低功耗架构突破:STM32H750 与 SD NAND (存储芯片)如何延长手环续航至 14 天

低功耗架构突破&#xff1a;STM32H750 与 SD NAND &#xff08;存储芯片&#xff09;如何延长手环续航至 14 天 卓越性能强化安全高效能效图形处理优势丰富集成特性 模拟模块实时监控保障数据完整性提升安全性与可靠性测量原理采样率相关结束语 在智能皮电手环及数据存储技术不…

Linux(11)——基础IO(上)

目录 一、理解文件 二、回顾C文件的接口 &#x1f4c4; C语言文件操作函数表 ​编辑&#x1f4c4; 三个文件流 三、系统文件I/O 1️⃣open 2️⃣close 3️⃣write 4️⃣read 四、文件描述符 &#x1f4a1;用户操作文件的底层逻辑是什么&#xff1f; &#x1f4…

ABP-Book Store Application中文讲解 - Part 9: Authors: User Interface

ABP-Book Store Application中文讲解 - Part 9: Authors: User Interface TBD 1. 汇总 ABP-Book Store Application中文讲解-汇总-CSDN博客 2. 前一章 ABP-Book Store Application中文讲解 - Part 8: Authors: Application Layer-CSDN博客 项目之间的引用关系。 ​​ 目…

Hive自定义函数案例(UDF、UDAF、UDTF)

目录 前提条件 背景 概念及适用场景 UDF&#xff08;User-Defined Function&#xff09; 概念 适用场景 UDAF&#xff08;User-Defined Aggregate Function&#xff09; 概念 适用场景 UDTF&#xff08;User-Defined Table-Generating Function&#xff09; 概念 适…

【学习笔记】Circuit Tracing: Revealing Computational Graphs in Language Models

Circuit Tracing: Revealing Computational Graphs in Language Models 替代模型(Replacement Model)&#xff1a;用更多的可解释的特征来替代transformer模型的神经元。 归因图(Attribution Graph)&#xff1a;展示特征之间的相互影响&#xff0c;能够追踪模型生成输出时所采用…

STM32标准库-TIM定时器

文章目录 一、TIM定时器1.1定时器1.2定时器类型1.1.1 高级定时器1.1.2通用定时器1.1.3基本定时器 二、定时中断基本结构预分频器时器计时器时序计数器无预装时序计数器有预装时序RCC时钟树 三、定时器定时中断3.1 接线图3.2代码3.3效果&#xff1a; 四、定时器外部中断4.1接线图…

Kafka 如何保证顺序消费

在消息队列的应用场景中&#xff0c;保证消息的顺序消费对于一些业务至关重要&#xff0c;例如金融交易中的订单处理、电商系统的库存变更等。Kafka 作为高性能的分布式消息队列系统&#xff0c;通过巧妙的设计和配置&#xff0c;能够实现消息的顺序消费。接下来&#xff0c;我…

【算法题】算法一本通

每周更新至完结&#xff0c;建议关注收藏点赞。 目录 待整理文章已整理的文章方法论思想总结模版工具总结排序 数组与哈希表栈双指针&#xff08;滑动窗口、二分查找、链表&#xff09;树前缀树堆 优先队列&#xff08;区间/间隔问题、贪心 &#xff09;回溯图一维DP位操作数学…

Modbus转Ethernet IP赋能挤出吹塑机智能监控

在现代工业自动化领域&#xff0c;小疆智控Modbus转Ethernet IP网关GW-EIP-001与挤出吹塑机的应用越来越广泛。这篇文章将为您详细解读这两者的结合是如何提高生产效率&#xff0c;降低维护成本的。首先了解什么是Modbus和Ethernet IP。Modbus是一种串行通信协议&#xff0c;它…

什么是终端安全管理系统(终端安全管理软件2024科普)

在当今数字化迅速发展的时代&#xff0c;企业面临着越来越多的信息安全威胁。为了应对这些挑战&#xff0c;保障公司数据的安全性和完整性&#xff0c;终端安全管理系统&#xff08;Endpoint Security Management System&#xff09;应运而生。 本文将为您深入浅出地科普2024年…

【JVM】Java类加载机制

【JVM】Java类加载机制 什么是类加载&#xff1f; 在 Java 的世界里&#xff0c;每一个类或接口在经过编译后&#xff0c;都会生成对应的 .class 字节码文件。 所谓类加载机制&#xff0c;就是 JVM 将这些 .class 文件中的二进制数据加载到内存中&#xff0c;并对其进行校验…