当前位置: 首页 > article >正文

C/C++ 结构体:. 与 -> 的区别与用法及其STM32中的使用

目录

  • 引言

  • 一、深入理解 C/C++ 结构体:.-> 的区别与用法

    • 1. .(点运算符)详解
    • 2. ->(箭头运算符)详解
    • 3. .-> 的等价与转换
    • 4. 常见错误与调试技巧
    • 5. C++ 特性与运算符重载
    • 6. 实战案例:链表与智能指针
    • 7. 最佳实践与性能考量
  • 二、在 STM32 单片机中,结构体的 .-> 使用详解

    • 1. 外设寄存器访问:-> 的绝对主场
    • 2. 库函数配置:.-> 的混合使用
    • 3. 动态分配与回调:-> 的灵活应用
    • 4. 常见错误与避坑指南
    • 5. 实战技巧与性能优化
  • 三、综合总结


引言

结构体(struct)在 C/C++ 及嵌入式开发中广泛应用。访问结构体成员时,使用点运算符(.)或箭头运算符(->)是基础操作。本文分为两大部分:

  1. 深入理解 C/C++ 结构体:讲解 .-> 的原理与用法,包括调试与最佳实践。
  2. 在 STM32 单片机中应用:结合外设寄存器、HAL 库及动态句柄场景,分享嵌入式开发中的实战示例与优化技巧。

一、深入理解 C/C++ 结构体:.-> 的区别与用法

1. .(点运算符)详解

作用:用于直接访问结构体变量的成员。

示例代码

#include <stdio.h>
#include <string.h>struct Student {char name[50];int age;float score;
};int main() {struct Student stu1;  // 定义结构体变量strcpy(stu1.name, "Alice");  // 使用 . 访问成员stu1.age = 20;stu1.score = 95.5;printf("Name: %s, Age: %d, Score: %.1f\n", stu1.name, stu1.age, stu1.score);return 0;
}

关键点

  • stu1 是一个结构体变量,使用 . 访问其成员。

2. ->(箭头运算符)详解

作用:用于访问结构体指针所指向的对象的成员。

示例代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>struct Student {char name[50];int age;float score;
};int main() {struct Student *stu_ptr = malloc(sizeof(struct Student));  // 动态分配内存strcpy(stu_ptr->name, "Bob");  // 使用 -> 访问指针指向的成员stu_ptr->age = 22;stu_ptr->score = 88.5;printf("Name: %s, Age: %d, Score: %.1f\n", stu_ptr->name, stu_ptr->age, stu_ptr->score);free(stu_ptr);  // 释放内存return 0;
}

关键点

  • stu_ptr 是一个结构体指针,使用 -> 访问其指向的结构体成员。
  • -> 等同于 (*ptr).member 的简写。

3. .-> 的等价与转换

struct Student *ps = &stu1;
// 等价示例:
ps->age = 25;      // 使用 ->
(*ps).age = 25;    // 解引用后用 .

链式访问时,-> 更简洁:

node->next->data;

4. 常见错误与调试技巧

场景错误示例正确写法调试思路
对指针使用 .stu_ptr.name = 20;stu_ptr->name = 20;检查变量类型
对实例使用 ->stu1->age = 20;stu1.age = 20;确认对象是否指针
空指针访问Node *n = NULL; n->x;添加空指针检查

调试技巧

  1. 使用 GDB:p stu1 vs p *stu_ptr
  2. 加断言:assert(ptr); ptr->field;
  3. 使用 Valgrind 检测内存问题

5. C++ 特性与运算符重载

  • 智能指针std::unique_ptr<T>std::shared_ptr<T> 支持 ->
  • 运算符重载:自定义 operator->() 实现代理模式。
struct Wrapper {Target* ptr;Target* operator->() { return ptr; }
};

6. 实战案例:链表与智能指针

6.1 传统 C 链表

struct Node { int data; struct Node *next; };

6.2 C++ 智能指针实现

#include <memory>
#include <iostream>struct Node { int data; std::unique_ptr<Node> next; };auto head = std::make_unique<Node>();
head->data = 1;
head->next = std::make_unique<Node>();
head->next->data = 2;

自动释放,无需手动 delete


7. 最佳实践与性能考量

  1. 优先使用智能指针与容器
  2. 注意结构体对齐与缓存友好
  3. 简化多级解引用为 p->next->x

二、在 STM32 单片机中,结构体的 .-> 使用详解

在 STM32 单片机开发中,结构体被广泛用于外设寄存器映射、HAL/LL 库配置及自定义数据管理。以下在不修改示例的基础上,保留原内容并优化说明。

1. 外设寄存器访问:-> 的绝对主场

// STM32F4 GPIO 寄存器定义
typedef struct {__IO uint32_t MODER;__IO uint32_t OTYPER;__IO uint32_t OSPEEDR;__IO uint32_t PUPDR;__IO uint32_t IDR;__IO uint32_t ODR;__IO uint32_t BSRR;__IO uint32_t LCKR;__IO uint32_t AFR[2];
} GPIO_TypeDef;#define GPIOA ((GPIO_TypeDef *)0x40020000U)// 设置 PA0 为推挽输出,高速,无上下拉
GPIOA->MODER  &= ~(3U << (0 * 2));
GPIOA->MODER  |=  (1U << (0 * 2));
GPIOA->OTYPER &= ~(1U << 0);
GPIOA->OSPEEDR |= (2U << (0 * 2));
GPIOA->PUPDR   &= ~(3U << (0 * 2));// 切换 PA0 电平
GPIOA->ODR ^= (1U << 0);

关键点

  • GPIOA 是指针宏,需用 ->
  • 可加 __DSB()/__ISB() 保证时序

2. 库函数配置:.-> 的混合使用

UART_HandleTypeDef huart2;
huart2.Instance = USART2;
huart2.Init.BaudRate = 115200;
huart2.Init.WordLength = UART_WORDLENGTH_8B;
huart2.Init.StopBits = UART_STOPBITS_1;
huart2.Init.Parity = UART_PARITY_NONE;
HAL_UART_Init(&huart2);
  • 配置结构体变量用 .
  • HAL 内部以 -> 操作寄存器

3. 动态分配与回调:-> 的灵活应用

DMA_HandleTypeDef *hdma = malloc(sizeof(DMA_HandleTypeDef));
hdma->Instance = DMA1_Channel1;
hdma->Init.Direction = DMA_MEMORY_TO_PERIPH;
HAL_DMA_Init(hdma);
void USART2_IRQHandler(void) {HAL_UART_IRQHandler(&huart2);
}
  • 建议 memset 清零并检查 NULL
  • 回调使用句柄指针,结合 HAL 生命周期管理

4. 常见错误与避坑指南

场景错误示例
变量误用 ->GPIO_InitStruct->Pin = ...;
指针未初始化访问hi2c->Instance = I2C1;

5. 实战技巧与性能优化

  • 位带别名提升 GPIO 操作速度
  • DMA 缓存一致性:使用 SCB_CleanDCache()
  • 多句柄存储于数组或链表

三、综合总结

  • 通用 C/C++ 场景

    • . 用于访问结构体实例成员,简洁直观
    • -> 用于解引用结构体指针并访问其成员,语法糖简化书写
  • STM32 嵌入式场景

    • . 用于配置 HAL/LL 库的局部结构体变量(InitStruct 等)
    • -> 用于外设寄存器映射(宏定义指针)、动态句柄和回调中访问成员
  • C++ 扩展

    • 智能指针(std::unique_ptr/std::shared_ptr)原生支持 ->,自动管理生命周期
    • 可自定义 operator-> 实现代理或链式访问
  • 性能与可靠性优化

    • 位掩码和位带操作加速单比特寄存器访问
    • DMA 传输需进行 Cache 管理(如 SCB_CleanDCache()SCB_InvalidateDCache()
    • 关注结构体对齐与数据局部性,提高缓存友好性

相关文章:

C/C++ 结构体:. 与 -> 的区别与用法及其STM32中的使用

目录 引言 一、深入理解 C/C 结构体&#xff1a;. 与 -> 的区别与用法 1. .&#xff08;点运算符&#xff09;详解2. ->&#xff08;箭头运算符&#xff09;详解3. . 与 -> 的等价与转换4. 常见错误与调试技巧5. C 特性与运算符重载6. 实战案例&#xff1a;链表与智能…...

docker中使用openresty

1.为什么要使用openresty 我这边是因为要使用1Panel&#xff0c;第一个最大的原因&#xff0c;就是图方便&#xff0c;比较可以一键安装。但以前一直都是直接安装nginx。所以需要一个过度。 2.如何查看openResty使用了nginx哪个版本 /usr/local/openresty/nginx/sbin/nginx …...

Jetpack Compose 中更新应用语言

在 Jetpack Compose 应用中更新语言需要结合传统的 Android 语言配置方法和 Compose 的重组机制。以下是完整的实现方案&#xff1a; 1. 创建语言管理类 object LocaleManager {private var currentLocale: Locale Locale.getDefault()fun setLocale(context: Context, local…...

Java 中的 super 关键字

个人总结&#xff1a; 1.子类构造方法中没有显式使用super&#xff0c;Java 也会默认调用父类的无参构造方法 2.当父类中没有无参构造方法&#xff0c;只有有参构造方法时&#xff0c;子类构造方法就必须显式地使用super来调用父类的有参构造方法。 3.如果父类没有定义任何构造…...

CMake基础:CMakeLists.txt 文件结构和语法

目录 1.CMakeLists.txt基本结构 2.核心语法规则 3.关键命令详解 4.常用预定义变量 5.变量和缓存 6.变量作用域与传递 7.注意事项 1.CMakeLists.txt基本结构 CMakeLists.txt 是 CMake 构建系统的核心配置文件&#xff0c;采用命令式语法组织项目结构和编译流程。主要用于…...

PCM音频数据的编解码

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、pandas是什么&#xff1f;二、使用步骤 1.引入库2.读入数据 总结 前言 提示&#xff1a;这里可以添加本文要记录的大概内容&#xff1a; 例如&#xff1a…...

WebView2 Win7下部分机器触屏失效的问题

这个问题官方给了解决的方案&#xff0c;相关地址&#xff0c;只需要在项目中运行这个代码即可 public static void DisableWPFTabletSupport(){TabletDeviceCollection devices Tablet.TabletDevices;if (devices.Count > 0){Type inputManagerType typeof(InputManager)…...

Ubuntu 通过指令远程命令行配置WiFi连接

前提设备已经安装了无线网卡。 1、先通过命令行 ssh 登录机器。 2、搜索wifi设备&#xff0c;指令如下&#xff1a; sudo nmcli device wifi 3、输入需要联接的 wifi 名称和对应的wifi密码&#xff0c;指令如下&#xff1a; sudo nmcli device wifi connect wifi名称 passw…...

线程池优雅关闭的哲学

引言 关于并发的哲学&#xff0c;本文将着重强调那些关于线程池优雅关闭的一些技巧&#xff0c;希望对你有所启发。 强制关闭线程池的弊端 对于池化的线程池&#xff0c;如果采用强制关闭的方式将线程池直接关闭&#xff0c;就可能存在上下文消息消息&#xff0c;无法的很好…...

11.8 LangGraph生产级AI Agent开发:从节点定义到高并发架构的终极指南

使用 LangGraph 构建生产级 AI Agent:LangGraph 节点与边的实现 关键词:LangGraph 节点定义, 条件边实现, 状态管理, 多会话控制, 生产级 Agent 架构 1. LangGraph 核心设计解析 LangGraph 通过图结构抽象复杂 AI 工作流,其核心要素构成如下表所示: 组件作用描述代码对应…...

8天Python从入门到精通【itheima】-41~44

目录 41节-while循环的嵌套应用 1.学习目标 2.while循环的伪代码和生活情境中的应用 3.图片应用的代码案例 4.代码实例【Patrick自己亲手写的】&#xff1a; 5.whlie嵌套循环的注意点 6.小节总结 42节-while循环的嵌套案例-九九乘法表 1.补充知识-print的不换行 2.补充…...

深度图数据增强方案-随机增加ROI区域的深度

主要思想&#xff1a;随机增加ROI区域的深度&#xff0c;模拟物体处在不同位置的形态。 首先打印一张深度图中的深度信息分布&#xff1a; import cv2 import matplotlib.pyplot as plt import numpy as np import seaborn as sns def plot_grayscale_histogram(image_path)…...

[Java恶补day6] 15. 三数之和

给你一个整数数组 nums &#xff0c;判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i ! j、i ! k 且 j ! k &#xff0c;同时还满足 nums[i] nums[j] nums[k] 0 。请你返回所有和为 0 且不重复的三元组。 注意&#xff1a;答案中不可以包含重复的三元组。 示例 1&a…...

Django模板及表单

什么是Django模板 Django模板是一种用于生成动态内容的文件&#xff0c;它使用Django模板语言&#xff08;Django Template Language&#xff0c;简称DTL&#xff09;来描述和渲染HTML页面。模板允许开发人员将动态数据与静态HTML结构分离&#xff0c;以实现更灵活和可维护的W…...

两个mysql的maven依赖要用哪个?

背景 <dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId> </dependency>和 <dependency><groupId>com.mysql</groupId><artifactId>mysql-connector-j</artifactId> &l…...

Kafka Consumer工作流程

Kafka Consumer工作流程图 1、启动与加入组 消费者启动后&#xff0c;会向 Kafka 集群中的某个 Broker 发送请求&#xff0c;请求加入特定消费者组。这个 Broker 中的消费者协调器&#xff08;Consumer Coordinator&#xff09;负责管理消费者组相关事宜。 2、组内分区分配&am…...

大腾智能 PDM 系统:全生命周期管理重塑制造企业数字化转型路径

在当今激烈的市场竞争中&#xff0c;产品迭代速度与质量已成为企业生存与发展的核心命脉。面对客户需求多元化、供应链协同复杂化、研发成本管控精细化等挑战&#xff0c;企业亟需一套能够贯穿产品全生命周期的数字化解决方案。 大腾智能PDM系统通过构建覆盖设计、研发、生产、…...

GATT 服务的核心函数bt_gatt_discover的介绍

目录 概述 1 GATT 基本概念 1.1 GATT 的介绍 1.2 GATT 的角色 1.3 核心组件 1.4 客户端操作 2 bt_gatt_discover函数的功能和应用 2.1 函数介绍 2.1 发现类型&#xff08;Discover Type&#xff09; 3 典型使用流程 3.1 服务发现示例 3.2 级联发现模式 3.3 按UUID过…...

【短距离通信】【WiFi】WiFi7关键技术之4096-QAM、MRU

目录 3. 4096-QAM 3.1 4096-QAM 3.2 QAM 的阶数越高越好吗&#xff1f; 4. MRU 4.1 OFDMA 和 RU 4.2 MRU 资源分配 3. 4096-QAM 摘要 本章主要介绍了Wi-Fi 7引入的4096-QAM对数据传输速率的提升。 3.1 4096-QAM 对速率的提升 Wi-Fi 标准一直致力于提升数据传输速率&a…...

C 语言学习笔记

文章目录 程序设计入门 --- C 语言第一周 程序设计与 C 语言1 计算机与编程语言:计算机怎么做事情的,编程语言是什么📒 1.1 计算机的普遍应用 —— 离了它,现代人可能不会“活”了**🌐 科学计算:计算机的“最强大脑”时刻****📊 数据处理:现代社会的“数字管家”***…...

【MySQL成神之路】MySQL函数总结

以下是MySQL函数的全面总结&#xff0c;包含概念说明和代码示例&#xff1a; 一、MySQL函数分类 1. 字符串函数 -- CONCAT&#xff1a;连接字符串 SELECT CONCAT(Hello, , World); -- 输出 Hello World -- SUBSTRING&#xff1a;截取子串 SELECT SUBSTRING(MySQL, 2, 3…...

线程池实战——数据库连接池

引言 作者在前面写了很多并发编程知识深度探索系列文章&#xff0c;反馈得知友友们收获颇丰&#xff0c;同时我也了解到友友们也有了对知识如何应用感到很模糊的问题。所以作者就打算写一个实战系列文章&#xff0c;让友友们切身感受一下怎么应用知识。话不多说&#xff0c;开…...

修改 vue-pdf 源码升级 pdfjs-dist 包, 以解决部分 pdf 文件显示花屏问题

文章目录 背景: 客户反馈有部分文件预览花屏 最终解决方案: 自己 fork vue-pdf 仓库, 修改 pdfjs-dist 版本, 升级到 3.3.122 (我是 vue2 项目 node 10 环境)修改源码中引用地址带有 pdfjs-dist/es5/ 的地方, 去掉 es5 , 另外如果还有报错自己搜一下 pdfjs-dist/ , 看看引用…...

基于moonshot模型的Dify大语言模型应用开发核心场景

基于moonshot模型的Dify大语言模型应用开发核心场景学习总结 一、Dify环境部署 1.Docker环境部署 这里使用vagrant部署&#xff0c;下载vagrant之后&#xff0c;vagrant up登陆&#xff0c;vagrant ssh&#xff0c;在vagrant 中使用 vagrant centos/7 init 快速创建虚拟机 安装…...

华为OD机试真题——字符串序列判定(2025B卷:100分)Java/python/JavaScript/C/C++/GO最佳实现

2025 B卷 100分 题型 本专栏内全部题目均提供Java、python、JavaScript、C、C++、GO六种语言的最佳实现方式; 并且每种语言均涵盖详细的问题分析、解题思路、代码实现、代码详解、3个测试用例以及综合分析; 本文收录于专栏:《2025华为OD真题目录+全流程解析+备考攻略+经验分…...

在Java的list.forEach(即 Stream API 的 forEach 方法)中,无法直接使用 continue 或 break 语句的解决办法

说明 在 Java 的 list.forEach&#xff08;即 Stream API 的 forEach 方法&#xff09;中&#xff0c;无法直接使用 continue 或 break 语句&#xff0c;因为它是一个终结操作&#xff08;Terminal Operation&#xff09;&#xff0c;依赖于 Lambda 表达式或方法引用。 有些时…...

Java面向对象高级学习笔记

面向对象高级 -类变量 类变量-提出问题 提出问题的主要目的就是让大家思考解决之道&#xff0c;从而引出我要讲的知识点 说:有一群小孩在玩堆雪人,不时有新的小孩加入,请问如何知道现在共有多少人在玩?&#xff0c;编写程序解决。 类变量快速入门 思考: 如果,设计一个int co…...

LLM之Agent:Mem0的简介、安装和使用方法、案例应用之详细攻略

LLM之Agent&#xff1a;Mem0的简介、安装和使用方法、案例应用之详细攻略 目录 Mem0的简介 1、Mem0的特点 2、性能&#xff1a; Mem0的安装及使用方法 1、安装 2、基本用法&#xff08;基本用法&#xff09; Mem0的案例应用 Mem0的简介 Mem0&#xff08;发音为“mem-ze…...

工商总局可视化模版-Echarts的纯HTML源码

概述 基于ECharts的工商总局数据可视化HTML模版&#xff0c;帮助开发者快速搭建专业级工商广告数据展示平台。这款模版设计规范&#xff0c;功能完善&#xff0c;适合各类工商监管场景使用。 主要内容 本套模版采用现代化设计风格&#xff0c;主要包含以下核心功能模块&…...

Spring AI 和 Elasticsearch 作为你的向量数据库

作者&#xff1a;来自 Elastic Josh Long, Philipp Krenn 及 Laura Trotta 使用 Spring AI 和 Elasticsearch 构建一个完整的 AI 应用程序。 Elasticsearch 原生集成了业界领先的生成式 AI 工具和服务提供商。查看我们关于超越 RAG 基础或使用 Elastic 向量数据库构建生产级应用…...