如何取消引用?

时间:2018-12-30 22:00:50

标签: c pointers dereference

我正在学习一个教程,他们想在其中写一个特定的值(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吗?

3 个答案:

答案 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。