这是如何取消引用的?
How is this dereferenced?
我正在学习一个教程,他们想在其中写入特定值 (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){}
}
现在,我有以下问题:
我们可以在不声明任何变量的情况下使用指针吗?
为什么要使用指向指针的指针?是因为,我们不能做ptr = 0x04000000吗?
广告。 1:C 允许将整数值转换为指针,反之亦然。您是否将(中间)转换分配给变量的天气无关紧要。代码部分(volatile uint32*)(0x04000000)
实际上是将整型字面量0x0400000
转换为uint32*
类型的指针;请注意 volatile,它会关闭所有编译器优化,并让代码在取消引用时实际访问相应的内存。
广告2:没有指向指针的指针; *((volatile uint32*)(0x04000000))
只是取消引用指针(已在 (1) 中解释)。
我猜这是关于 GameBoy Advance 开发的。
您可以在不声明任何变量的情况下写入内存地址,指针是一种表示内存地址的值类型,您可以写入和读取它而无需将其存储在任何地方。
它不是指向指针的指针,它是一个硬编码地址,被强制转换为 (volatile uint32*)
,并且宏在前面添加了 *
运算符只是为了避免您编写它,这只是令人困惑。
我最近在做GBA开发的框架,也许你可以从there中挑选一些资料或代码,不过注意代码是C++14。
只是一个评论。所有这些只能由实现定义,因为语言本身没有寄存器存在于众所周知地址的概念。
标准在 6.3.2.3 指针 §5 中说(强调我的):
An integer may be converted to any pointer type. Except as previously specified, the
result is implementation-defined, might not be correctly aligned, might not point to an
entity of the referenced type, and might be a trap representation.
这意味着这是有效的 C,前提是实现允许它有意义:
unsigned int *ptr;
ptr = 0x04000000;
*ptr = 0x403;
它只是使用命名指针来访问特定地址。不用那样命名指针也可以做到:
* ((unsigned int *) 0x04000000) = 0x403;
让我们看看它是如何工作的:
(unsigned int *) 0x04000000
将 unsigned int 转换为指向 unsigned 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;
我正在学习一个教程,他们想在其中写入特定值 (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){}
}
现在,我有以下问题:
我们可以在不声明任何变量的情况下使用指针吗?
为什么要使用指向指针的指针?是因为,我们不能做ptr = 0x04000000吗?
广告。 1:C 允许将整数值转换为指针,反之亦然。您是否将(中间)转换分配给变量的天气无关紧要。代码部分(volatile uint32*)(0x04000000)
实际上是将整型字面量0x0400000
转换为uint32*
类型的指针;请注意 volatile,它会关闭所有编译器优化,并让代码在取消引用时实际访问相应的内存。
广告2:没有指向指针的指针; *((volatile uint32*)(0x04000000))
只是取消引用指针(已在 (1) 中解释)。
我猜这是关于 GameBoy Advance 开发的。
您可以在不声明任何变量的情况下写入内存地址,指针是一种表示内存地址的值类型,您可以写入和读取它而无需将其存储在任何地方。
它不是指向指针的指针,它是一个硬编码地址,被强制转换为 (volatile uint32*)
,并且宏在前面添加了 *
运算符只是为了避免您编写它,这只是令人困惑。
我最近在做GBA开发的框架,也许你可以从there中挑选一些资料或代码,不过注意代码是C++14。
只是一个评论。所有这些只能由实现定义,因为语言本身没有寄存器存在于众所周知地址的概念。
标准在 6.3.2.3 指针 §5 中说(强调我的):
An integer may be converted to any pointer type. Except as previously specified, the result is implementation-defined, might not be correctly aligned, might not point to an entity of the referenced type, and might be a trap representation.
这意味着这是有效的 C,前提是实现允许它有意义:
unsigned int *ptr;
ptr = 0x04000000;
*ptr = 0x403;
它只是使用命名指针来访问特定地址。不用那样命名指针也可以做到:
* ((unsigned int *) 0x04000000) = 0x403;
让我们看看它是如何工作的:
(unsigned int *) 0x04000000
将 unsigned int 转换为指向 unsigned 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;