完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
结构体在使用其某成员变量时用:
结构体名.结构体成员 方式 忽然想到 GPIOA->ODR 这个结构,隐约记得这个和指针有关,这个结构具体是啥意思来着,和引用结构体成员变量的方式有什么区别? |
|
相关推荐
7个回答
|
|
为了彻底弄清这个问题,让我们来看看下面的问题
如下两个表达式,怎样去计算它的结果? 它的结果到底是什么? (1)结构体变量.成员变量 (2)结构体变量指针->成员变量 首先要明白(1)中的结果是一个变量值,类似 int a 一样,都是变量; (2)中的结果是一个指针指向的值,跟普通的 *(int *a) 也一样,最终结果是变量。 对编译器来说,要知道一个变量的值,必须先找到它的地址,再确定该变量的类型, 知道了类型,自然就知道数据的字节长度了;而要知道一个指针,就是找到它的地址 即可,这时候的地址即可理解为指针,通过指针指向的地址去找它所存储的变量。 在(1)中的结果是个变量: 要确定它的值,就得先确定它的地址,再确定它的变量类型(即数据占用的字节长度) 它的地址 = 结构体变量首地址 + 成员变量在结构体中的偏移地址 它的类型 = 成员变量前面的类型修饰符 至于成员变量的类型也可为普通类型,比如 int, short, char 等,甚至它也可以为结构体 类型、联合类型、枚举类型等。 在(2)中的结果是个指针(即地址)指向的变量: 只要确定出它的地址即可 它的地址 = 结构体变量首地址 + 成员变量在结构体中的偏移地址它的类型 = 成员变量前面的类型修饰符 它的结果就有点类似于:*(地址) 对地址取* ,结果是变量 在某些代码中,你甚至可以看到以下这样的表达: (3)( (结构体类型 *)0 )->成员变量 这是什么意思呢?它的计算结果是一个地址?!对,它是个地址 将0地址强制转换成一个结构体类型,通过结构体类型就可以访问结构体 内部的成员变量,说它是一个地址,那么它的地址是多少呢? (3)的地址 = 0 + 成员变量在结构体中的偏移地址 = 成员变量在结构体中的偏移地址 通过上面的计算,可以看出(3)的结果是一个地址,它的大小刚好等于成员变量 在结构体中的偏移地址,所以(3)这种表达式也有一个特殊用途,就是用 来计算一个结构体成员在结构体中的字节偏移量,所以也可以把它当做一个 变量来使用。 接着分析: #define PERIPH_BASE ((uint32_t)0x40000000) /*!< Peripheral base address in the alias region */ #define APB2PERIPH_BASE (PERIPH_BASE + 0x10000) #define GPIOA_BASE (APB2PERIPH_BASE + 0x0800) #define GPIOA ((GPIO_TypeDef *) GPIOA_BASE) typedef struct { __IO uint32_t CRL; __IO uint32_t CRH; __IO uint32_t IDR; __IO uint32_t ODR; __IO uint32_t BSRR; __IO uint32_t BRR; __IO uint32_t LCKR; } GPIO_TypeDef; GPIOA_BASE =0x40000000 + 0x10000 + 0x0800 = (uint32_t) 0x40010800 GPIOA->ODR = ( (GPIO_TypeDef *)0x40010800) ->ODR = *(0x40010800 + 4*3) = *(0x40010800 + 12) = *((GPIO_TypeDef *)0x4001080C) 好,我们来查看STM32F10X的数据手册,查看存储器映像来核对一下 0x4001080C 这个地址 file:///C:/Users/Administrator/Documents/My%20Knowledge/temp/523943fc-1ee0-42ef-b893-70e450d0dbe6/128/index_files/ad3edc74-58d7-4a84-92ab-bf9ee189544b.png 可以看出GPIO端口A的基地址为:0x40010800 再看ODR在结构体内的偏移地址 file:///C:/Users/Administrator/Documents/My%20Knowledge/temp/523943fc-1ee0-42ef-b893-70e450d0dbe6/128/index_files/d206c303-06b4-4027-a561-202fe00b65b3.png 可以看出GPIOx_ODR的偏移为:00CH (x是统称,可以是A,B,C,D,E,F,G) 那么 从手册中,我们可以看出 GPIOA->ODR 最终地址为:0x40010800 + 00ch = 0x4001080C 跟前面的宏展开计算结果一致!那么 GPIOA->ODR = VAL; 就等效于 (*(volatile uint32_t*)(0x4001080C)) = VAL; |
|
|
|
把结构体看做一个特定类型的变量,如果这个变量是实体的,就用点,如果是指针就用箭头
|
|
|
|
struct AAA {
int a; char b; }; struct AAA q; 访问成员就用:q.a; struct AAA *p; 访问成员就用:p->a; |
|
|
|
明白了,谢谢啦
|
|
|
|
嗯嗯,我记得是和指针有关来着,谢啦
|
|
|
|
p->a等价于(*p).a
|
|
|
|
正好在了解这方面的知识
|
|
|
|
只有小组成员才能发言,加入小组>>
请问下图大疆lightbridge2遥控器主板电源芯片型号是什么?
4439 浏览 1 评论
使用常见的二极管、三极管和mos做MCU和模组的电平转换电路,但是模组和MCU无法正常通信,为什么?
311浏览 2评论
为了提高USIM卡电路的可靠性和稳定性,在电路设计中须注意的点有哪些?
295浏览 2评论
311浏览 2评论
310浏览 2评论
352浏览 2评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-22 02:28 , Processed in 0.904726 second(s), Total 59, Slave 52 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号