具有可寻址GPR文件的CPU,寄存器变量的地址以及存储器和寄存器之间的别名

时间:2014-11-13 18:17:25

标签: c language-lawyer avr avr-gcc

背景

某些CPU(例如Atmel AVR)具有通用寄存器文件,该文件也可作为主存储器的一部分进行寻址 - 请参见第7.4节中的图7-2和图中的段落。

WG14的想法是什么?

鉴于此,C委员会为何选择

register int ri;
int* pi = &ri;
根据{{​​3}}第6.7.1节的脚注101,

普遍构成不良?考虑到上面的代码在至少一个处理器上是有意义的,并且C向后弯曲以适应远比AVR更陌生(和更稀缺!)的目标,是不是未定义或实现定义的行为更有意义?

  

101)实施可以将register声明简称为auto   宣言。但是,无论是否实际使用了可寻址存储,地址   使用存储类说明符register声明的对象的任何部分都不能   显式计算(通过使用6.5.3.2中讨论的一元&运算符)   或隐式(通过将数组名称转换为指针,如6.3.2.1中所述)。从而,   唯一可以应用于使用存储类说明符声明的数组的运算符   registersizeof

我刚刚通过指针更改了CPU寄存器。笏?!

此外,使用GCC显式寄存器变量扩展,可以指示编译器将变量放入特定寄存器。在这种情况下,您可以获得一个与寄存器变量别名的指针,如下所示:

register int ri asm("r15") = 0;
int* pi = (int*)0x15;
/* pi now aliases ri */
*pi = 42;
/* ri is 42 now */
assert(ri == 42);

海湾合作委员会如何处理此类案件?让我感到非常奇怪的是,这样的事情还没有被考虑过......或者有没有?

1 个答案:

答案 0 :(得分:4)

C是一种抽象语言,定义时不知道最终会实现它的机器。 C的定义并不假设底层机器甚至会以常规形式拥有寄存器(或堆栈,或连续内存,或与真实机器上存在的此问题无关的许多其他内容)

关键是register 意味着应该为变量分配一个机器寄存器。关键字的含义是变量不能获取其地址;然后,理论上编译器能够对其执行更好的优化,因为它减少了可能修改变量的路径数。获取register变量的地址在C 中没有意义,无论它运行在哪个处理器上,因为registeran incredibly badly-named keyword(以最多命名)显而易见的优化,它使具体意味着不应该采取地址。这就是它的意思。

AVR的智能编译器应该能够进行优化而不需要你提示它(无论如何(实际上关键字是无用的,因为任何半群编译器都可以检测到它什么时候适用,因为基本上没有明确定义引用auto对象而不明确显示其地址的方法。