C 语言点运算符( . )和箭头运算符( -> )的区别(以单片机寄存器结构体定义为例)

本文详细介绍了单片机中GPIO寄存器的地址偏移封装方法,通过定义宏来访问不同寄存器内容,并讨论了结构体在封装中的应用。GPIOC_BASE作为基地址,通过地址偏移获取各寄存器指针。同时,展示了如何通过结构体和指针使用点运算符(.)和箭头运算符(->)来访问成员,以实现寄存器的操作。此外,还对比了结构体变量直接访问成员与指针访问成员的区别。
摘要由CSDN通过智能技术生成

在单片机寄存器封装的时候,一般库都会选择用地址偏移的办法完成。

    #define GPIOC_CRL *(unsigned int*)(GPIOC_BASE+0x00)

    #define GPIOC_CRH *(unsigned int*)(GPIOC_BASE+0x04)

    #define GPIOC_IDR *(unsigned int*)(GPIOC_BASE+0x08)

    #define GPIOC_ODR *(unsigned int*)(GPIOC_BASE+0x0C)

    #define GPIOC_BSRR *(unsigned int*)(GPIOC_BASE+0x10)

    #define GPIOC_BRR *(unsigned int*)(GPIOC_BASE+0x14)

    #define GPIOC_LCKR *(unsigned int*)(GPIOC_BASE+0x18)

GPIOC_BASE是一个基地址,记录的是GPIOC寄存器的起始地址,是一个普通的常量,假设这个常量为C。

(unsigned int*)代表强制转换,即将后面的常量转变为一个地址指针,且类型为无符号整型。总的来说,C就是一个指向无符号整型的地址指针。如果没有强制转换,编译器会认为C就是一个普通的常量。

前面再加(*),就是指针的取内容,代表是取出在C地址的内容。所以GPIOC_CRL等内容并不是一个地址(指针),而是对应地址上面的内容。

    typedef struct

    {

        uint32_t CRL; /*GPIO 端口配置低寄存器 地址偏移: 0x00 */

        uint32_t CRH; /*GPIO 端口配置高寄存器 地址偏移: 0x04 */

        uint32_t IDR; /*GPIO 数据输入寄存器 地址偏移: 0x08 */

        uint32_t ODR; /*GPIO 数据输出寄存器 地址偏移: 0x0C */

        uint32_t BSRR; /*GPIO 位设置/清除寄存器 地址偏移: 0x10 */

        uint32_t BRR; /*GPIO 端口位清除寄存器 地址偏移: 0x14 */

        uint16_t LCKR; /*GPIO 端口配置锁定寄存器 地址偏移: 0x18 */

    }GPIO_TypeDef;

然后会封装一个结构体,命名为GPIO_TypeDef,存在7个成员。

 #define GPIOC ((GPIO_TypeDef *) GPIOC_BASE)

之后GPIOC宏定义为GPIO_TypeDef类型的指针。GPIOC是一个指向GPIO_TypeDef类型,且初始位置为GPIOC_BASE的指针。这里和前面不同的地方在于,前面没有(*),也就是不需要取内容。

typedef struct          // 定义一个结构体类型
{
    char name[20];      // 结构体成员:name
    int height;             // 结构体成员:height
}STUDENT;
    
STUDENT data;              // 声明一个结构体变量
data.height = 180;          // 结构体变量通过点运算符( . )访问

以上是我们经常用的结构体定义和访问,可以看到我们并不是定义一个指针,而是定义了一个普通结构体变量,然后通过点运算符(.)去访问成员。那GPIOC作为一个指针,是如何访问结构体成员内部的结构。

  • 点运算符的左操作数必须是一个结构或者一个联合,而右操作数必须是该类型(结构或联合)成员的名字。
  • 运算符 -> 也可用于选择结构或联合的成员,但是箭头运算符的左操作数必须是一个指针,它指向一个结构或联合类型。右操作数是该结构或联合成员的名字。

所以一般寄存器的访问都是通过箭头运算符进行访问的。例如GPIOC->CRL= 0x00000001,可对CRL寄存器进行赋值。

typedef struct          // 定义一个结构体类型
{
    char name[20];      // 结构体成员:name
    int height;             // 结构体成员:height
}STUDENT;
    
STUDENT data;              // 结构体变量
STUDENT *pdata;              //结构体指针变量

 //点运算符( . )访问
data.height = 180;         
 //箭头运算符( -> )访问
pdata->height = 180;
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值