从stm32f446xx.h
我们有GPIO_TypeDef的定义
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 */
} GPIO_TypeDef;
这用于初始化某些GPIO外设。专注于GPIOA:
#define PERIPH_BASE ((uint32_t)0x40000000)
#define AHB1PERIPH_BASE (PERIPH_BASE + 0x00020000)
#define GPIOA_BASE (AHB1PERIPH_BASE + 0x0000)
#define GPIOA ((GPIO_TypeDef *) GPIOA_BASE)
所以我的问题是:
#define
指令是否声明并初始化结构并将其放在指向`GPIOA_BASE的地址处?或者是define语句只是声明结构而不是初始化其成员?
如果成员没有明确定义,他们的地址位置如何正确?我们如何知道GPIOA->MODER
与GPIOA_BASE
的地址相同?同样,我们如何知道GPIOA->ODR
会导致地址GPIOA_BASE
+偏移0x014
?这只是因为当我们声明结构并告诉它它位于GPIOA_BASE
时使用#define GPIOA ((GPIO_TypeDef *) GPIOA_BASE)
命令时,所有它的成员变量都按顺序在内存中声明和初始化它们出现在结构GPIOA_TypeDef
中?这是有道理的,因为每个占用4个字节,但我不确定是否是这种情况。
如果成员变量未按结构中列出的顺序声明,那么他们如何分配内存地址?
答案 0 :(得分:1)
名称“C”用于描述两件事:
一系列语言,它们以相当一致的方式将源代码构造映射到目标机器构造。通常没有“标准”记录如何执行此类映射,异常目标平台的实现与更常见的平台的实现不同,但类似平台的编译器通常表现相似。
一种语言,其中仅包含C11标准规定的功能,并且通常省略了在所有平台上未实现的功能,即使类似平台的C编译器也会对它们进行类似的处理。
您在上面引用的代码是专为处理第一个系列语言的编译器而设计的,这些编译器可以满足ARM处理器的需求。在该语言中,结构的每个项目将被放置在满足其对齐要求的最低偏移处。 C11标准或其任何前身都不要求编译器保证以这种方式布置结构,对于那些有时以其他方式指示该事实的人来说,也不要采用任何方便的方式。从C11标准的观点来看,结构元素可以任意放置,受到相对较少的约束。我认为C89的作者可能认为编译器编写者会在有或没有授权的情况下按顺序进行布局,除非在罕见的平台上可能有其他令人信服的理由,因此没有理由要求他们表现得像他们一样无论如何都要去。然而,有些人似乎认为缺乏授权意味着公开邀请任意安排事情,任何依赖特定布局的代码都应被视为“有缺陷”。