c-这是如何被取消引用的



我正在学习一个教程,在那里他们想写一个特定的值(0x0403)来注册(地址0x04000000)

据我所知,可以这样做

unsigned int 32 *ptr;
ptr = 0x04000000
*ptr = 0x403

然而,他们正在做以下事情:

#define REG_DISP      *((volatile uint32*)(0x04000000))
#define VIDEOMODE_3                            0x0003
#define BGMODE_2                               0x0400
int main()
{
REG_DISP = VIDEOMODE_3 | BGMODE_2;
while(1){}
}

现在,我有以下问题:

  1. 我们可以在不声明任何变量的情况下使用指针吗?

  2. 为什么使用指向指针的指针?是因为,我们不能执行ptr=0x04000000吗?

只是一句话。所有这些只能由实现定义,因为语言本身没有居住在已知地址的寄存器的概念。

标准只是在6.3.2.3 Pointers§5(强调我的)中说:

整数可以转换为任何指针类型。除先前规定外结果是定义了实现,可能没有正确对齐,可能没有指向引用类型的实体,并且可能是陷阱表示。

这意味着这是有效的C,只要实现允许它有意义:

unsigned int *ptr;
ptr = 0x04000000;
*ptr = 0x403;

它只是使用一个命名指针来访问特定地址。它可以在不以这种方式命名指针的情况下完成:

* ((unsigned int *) 0x04000000) = 0x403;

让我们看看它是如何工作的:

  • (unsigned int *) 0x04000000将无符号int转换为指向无符号int的指针
  • * ((unsigned int *) 0x04000000)取消引用该指针
  • * ((unsigned int *) 0x04000000) = 0x403;为指向变量赋值

当您想要访问物理寄存器时,您需要要求编译器立即写入值,而不是将其保留在内部寄存器中,根据规则,这是允许的,就好像规则一样。这就是volatile限定符的含义。由于它专门用于特定的实现,因此它是完全合法的,前提是您可以确定unsigned int在该实现中有32位,用于写入

volatile unsigned int *ptr;
ptr = 0x04000000;
*ptr = 0x403;

* ((volatile unsigned int *) 0x04000000) = 0x403;

Ad。1:C允许将整数值转换为指针,反之亦然。是否将(中间)转换指定给变量并不重要。代码部分(volatile uint32*)(0x04000000)实际上将整数字面值0x0400000转换为类型uint32*的指针;请注意volatile,它关闭了任何编译器优化,并允许代码在取消引用时实际访问相应的内存。

广告2:没有指向指针的指针;CCD_ 9只是取消引用指针(已经在(1)中进行了解释)。

我想这是关于GameBoy Advance的开发。

您可以在不声明任何变量的情况下写入内存地址,指针是一种表示内存地址的值类型,您可以从中写入和读取,而无需将其存储在任何位置。

它不是指向指针的指针,而是一个硬编码地址,它被强制转换为(volatile uint32*),宏在前面添加*运算符只是为了避免您编写它,这只是令人困惑。

这些天我正在为GBA开发开发一个框架,也许你可以从中挑选一些信息或代码,记住代码是C++14。

最新更新