我正在学习一个教程,他们想在其中写一个特定的值(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吗?
答案 0 :(得分:1)
只是一句话。所有这些都只能由实现定义,因为该语言本身没有存在于已知地址的寄存器的概念。
该标准仅在6.3.2.3指针§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;
答案 1 :(得分:0)
广告。 1:C允许将整数值转换为指针,反之亦然。您将(中间)转换分配给变量的天气与否无关紧要。代码部分(volatile uint32*)(0x04000000)
实际上将整数文字0x0400000
转换为类型uint32*
的指针;请注意volatile,它会关闭所有编译器优化功能,并在每当取消引用时让代码实际访问相应的内存。
广告2:没有指向指针的指针; *((volatile uint32*)(0x04000000))
仅取消引用指针(在(1)中已对此进行了说明。
答案 2 :(得分:0)
我想这与GameBoy Advance开发有关。
您可以在不声明任何变量的情况下写入内存地址,指针是代表内存地址的一种值类型,您可以在其中进行读写操作而无需将其存储在任何地方。
这不是指向指针的指针,而是一个硬编码的地址,它被强制转换为(volatile uint32*)
,并且宏在前面添加了*
运算符只是为了避免您编写它,这只是令人困惑。
这几天,我正在为GBA开发构架,也许您可以从there中挑选一些信息或代码,但是请注意,代码是C ++ 14。