赞
踩
目录
(1)采用struct和 typedef struct 声明结构体是有区别的
typedef和用struct都可以用来定义结构体,采用struct和采用typedef struct 声明结构体是有区别的。
结构体是一种自定义的数据类型,可以将不同类型的数据组合在一起,构成一个组合型数据结构。
- struct b_type
- {
- uiny32_t _reserved0:27; /*! bit:0..26 */
- uiny32_t Q:1; /*! bit:27 */
- uiny32_t V:1; /*! <bit:28 */
- uiny32_t C:1; /*! <bit:29 */
- uiny32_t Z:1; /*! <bit:30 */
- uiny32_t N:1; /*! <bit:31 */
- };
其中,struct是声明结构体的关键字,b_type是结构体的名称。{}里的内容是结构体的成员。在b_type结构体里有6个成员,它们的数据类型都是uint32_t。结构体中各成员的数据类型可以不同。
上面的声明的结构体并没有定义结构体变量,只是建立了一个名为b_type的结构体类型。如果仅仅如此,编译的时候,是不会给这个结构体分配存储单元的。
上面声明的b_type结构体可以通过下面的语句定义变量:
struct b_type b; // b为结构体变量名
也可以在声明结构体时定义结构体变量,其效果是相同的:
- struct b_type
- {
- uiny32_t _reserved0:27; /*! bit:0..26 */
- uiny32_t Q:1; /*! bit:27 */
- uiny32_t V:1; /*! <bit:28 */
- uiny32_t C:1; /*! <bit:29 */
- uiny32_t Z:1; /*! <bit:30 */
- uiny32_t N:1; /*! <bit:31 */
- } b;
此外,在声明结构体时还可以不指定结构体类型名,直接定义结构体变量:
- // 直接定义结构体变量GPIO_InitTypeDef
- struct
- {
- uint32_t Pin;
- uint32_t Mode;
- uint32_t Pull;
- uint32_t Speed;
- } GPIO_InitTypeDef;
结构体类型和结构体变量是不同的概念,编译时只会对变量分配内存空间,并且只可对变量进行赋值等操作。因此,声明结构体后,如果要使用它,就一定要定义该结构体的变量。
typedef是C语言中的关键字,它的作用是为其后面的数据类型定义一个“别名”,新的名字。此处所说的其后的数据类型可以是int、char等常用的数据类型,也可以是结构体struct这样的自定义数据类型。使用typedef的目的是简化类型声明,给变量类型定义新名字。
如下,以struct声明了b_type结构体并定义变量b:
- struct b_type // b_type不是变量名,而是结构体名,并且可以省略
- {
- // 类型成员名
- } b; // b是结构体变量
如果,再定义另一个结构体变量aaa,可以:
struct b_type aaa;
- typedef struct a_type // a_type是结构体名称,可以省略
- {
- // 类型 成员名
- } a_type_new; // a_type_new是结构体新的成员名称,不是变量名
此处,{}后面的a_type_new不再是结构体变量,而是结构体a_type的别名。此时若定义该结构体的变量aaa,可以:
- struct a_type aaa;
- 或
- struct a_type_new aaa;
- /**
- * @brief General Purpose I/O
- */
-
- typedef struct
- {
- __IO uint32_t MODER; /*!< GPIO port mode register, Address offset: 0x00 */
- __IO uint32_t OTYPER; /*!< GPIO port output type register, Address offset: 0x04 */
- __IO uint32_t OSPEEDR; /*!< GPIO port output speed register, Address offset: 0x08 */
- __IO uint32_t PUPDR; /*!< GPIO port pull-up/pull-down register, Address offset: 0x0C */
- __IO uint32_t IDR; /*!< GPIO port input data register, Address offset: 0x10 */
- __IO uint32_t ODR; /*!< GPIO port output data register, Address offset: 0x14 */
- __IO uint32_t BSRR; /*!< GPIO port bit set/reset register, Address offset: 0x18 */
- __IO uint32_t LCKR; /*!< GPIO port configuration lock register, Address offset: 0x1C */
- __IO uint32_t AFR[2]; /*!< GPIO alternate function registers, Address offset: 0x20-0x24 */
- __IO uint32_t BRR; /*!< GPIO Bit Reset register, Address offset: 0x28 */
- } GPIO_TypeDef;

其中,数据类型前面的__IO在固件库中通过define宏定义为volatile:
# define __IO volatile;
C语言中,变量前加volatile是提醒编译器不用对变量进行优化,调用该变量时,每次都到变量所在寄存器中去读它的内容。
进一步地,在单片机中,比如在stm32g474xx.h文件中,很多形如GPIO_TypeDef的结构体,都是结构体名称,而不是结构体的变量。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。