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

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()
    • 关注结构体对齐与数据局部性,提高缓存友好性

相关文章:

  • 基于MATLAB实现传统谱减法以及两种改进的谱减法(增益函数谱减法、多带谱减法)的语音增强
  • mysql:MVCC机制
  • leetcode 39. Combination Sum和40. Combination Sum II
  • 人工智能100问☞第32问:什么是迁移学习?
  • 机器学习课程设计报告 —— 基于口红数据集的情感分析
  • 【免杀】C2免杀技术(九)DLL注入前置篇
  • 事务操作语句
  • 美团2025年校招笔试真题手撕教程(三)
  • [Linux]磁盘分区及swap交换空间
  • React整合【ECharts】教程002:折线图的构建和基本设置
  • 疫情社区管理登记系统
  • 基于TypeScript的全栈待办事项应用Demo
  • binlog解析工具——binlog2sql
  • 机械师安装ubantu双系统:二、磁盘分区
  • 【MPC控制 - 从ACC到自动驾驶】5. 融会贯通:MPC在ACC中的优势总结与知识体系构建
  • 浏览器游戏的次世代革命:WebAssembly 3.0 实战指南
  • 人脑能够通过视频信息快速建模出现实场景,原因有哪些方面?
  • 人工智能数学基础实验(一):智能推荐系统实战
  • CA自签名证书创建--证书链生成脚本
  • 强化学习在大模型中的应用详解
  • wordpress 自动换行/一键优化软件
  • 网站导航css源代码/百度快速收录入口
  • 网站开发以图片为背景/标题关键词优化技巧
  • 滨江做网站/南宁seo优化
  • 百度做一个网站怎么做呢/个人如何推广app
  • 太原推广型网站制作/盐城seo培训