【发布时间】:2021-03-09 19:02:36
【问题描述】:
我很想了解为什么我们需要对一个绝对物理内存地址进行类型转换,以及它对编译器有什么影响,如果我们对地址进行类型转换,或者我们不?
我在寻找访问绝对物理地址的不同方法时遇到了following code。
例如这里我们有一个地址0x40020C00,它指向PORTA(有多个这样的端口,如下所示)。
如果我们要访问此地址的偏移量之一以写入一些位(为了将 I/O 引脚配置为输入/输出,然后只需切换 LED),我们可以将其编码如下:
typedef struct
{
uint32_t MODER; // mode register, offset: 0x00
uint32_t OTYPER; // output type register, offset: 0x04
uint32_t OSPEEDR; // output speed register, offset: 0x08
uint32_t PUPDR; // pull-up/pull-down register, offset: 0x0C
uint32_t IDR; // input data register, offset: 0x10
uint32_t ODR; // output data register, offset: 0x14
uint32_t BSRR; // bit set/reset register, offset: 0x18
uint32_t LCKR; // configuration lock register, offset: 0x1C
uint32_t AFRL; // GPIO alternate function registers, offset: 0x20
uint32_t AFRH; // GPIO alternate function registers, offset: 0x24
} GPIO_t;
volatile GPIO_t* const portd = (GPIO_t*)0x40020C00;
int main(void)
{
*rcc_ahb1enr |= (1 << 3); // enable PortD's clock
uint32_t moder = portd->MODER;
moder |= (1 << 16);
moder &= ~(1 << 17);
portd->MODER = moder;
while (1) {
portd->ODR |= (1 << 8); // led-on
sleep(500);
portd->ODR &= ~(1 << 8); // led-off
sleep(500);
}
}
我的问题是:
在这一行中,
volatile GPIO_t* const portd = (GPIO_t*)0x40020C00;为什么我们要用数据的返回类型(GPIO_t*)类型转换绝对内存地址(0x40020C00), 指针何时具有正确的返回类型?
注意:我知道为什么它被编码为 volatile 和 const 指针(即因为它是寄存器的绝对物理地址,我们不希望编译器优化用于访问这些地址的变量和我们承诺不改变指针地址。)
感谢您的解释/答案,并提前致谢!
【问题讨论】:
-
0x40020C00是一个整数,一般认为与指针类型不兼容。因此需要显式转换。不知道你在问什么。 -
这么说吧,如果我将地址类型转换为
(uintptr_t *)或(uint32_t *),会不会正确(假设从地址返回的数据是uint32_tlong) ?甚至有必要进行这种铸造吗?我不能只使用指针而不进行转换吗? -
您将其转换为您希望从该地址读取的类型的指针,就是这样。如果不强制转换,它将根本无法编译或抛出警告。
标签: c pointers memory casting type-conversion