在编写C编译器的上下文中,‘Register’关键字有什么用处?我最近看到一条声明,说在符号表中创建条目时,‘Register’关键字对编译器编写者很有用.然而,我找不到任何关于这一特定用法的具体例子或解释.

我知道‘Register’关键字暗示编译器应该将变量存储在处理器寄存器中以进行优化访问.然而,在现代编译器中,确定变量在寄存器中的最佳分配通常是编译器的责任,这使得‘Register’关键字对大多数程序员来说已经过时.

我的具体问题集中在理解任何潜在的场景或代码示例上,在这些场景或代码示例中,在编写C编译器的上下文中,‘Register’关键字可能是合理的或有用的.我感兴趣的是找到任何与前面提到的语句一致的历史来源或见解,从而阐明‘Register’在编译器开发中的实用价值.

请注意,我唯一感兴趣的是在用C编写编译器时,理解‘Register’关键字的可能相关性,而不是将其用作常规的C程序员.

推荐答案

据我所知,根据C标准,只有两个register的属性是必需的:不能接受地址,也不能与_Alignas一起使用.因此,您的编译器must对如下代码发出诊断:

register int foo;
&foo; // constraint violation

register int bar[3]; // basically useless but not an error by itself
bar; // constraint violation, decays to pointer
bar[1]; // likewise

register _Alignas(16) int baz; // constraint violation

(顺便说一句,GCC实际上允许在没有诊断的情况下使用register int bar[3]; bar[1];;但除非您使用-pedantic,否则它不会声称是符合要求的C实现,在这种情况下,您确实会收到应该得到的警告.)

请注意,"诊断"不一定是错误;警告就足够了.因此,对于上面的代码片段,如果您愿意,可以发出警告,然后继续以任何您想要的方式处理它们(例如,忽略register声明).

当然,由于它是一个关键字,如果它出现在语法上不允许的地方,例如作为标识符,您必须发出诊断.

int register;
void register(void);

其他一切都由您作为实施者自行决定.如果您愿意,您可以完全忽略它,而且在很大程度上,这就是现代编译器所做的.

该标准对register的本意是"建议 传统上,这可能在寄存器分配过程中使用.如果您处于机器寄存器用完的情况下,需要将一些变量溢出到内存中,那么您可能会优先考虑register个变量,并try 首先溢出非register个变量.例如,如果您有

int a,b,c,d,e,f,g,h;
register int r;

那么,如果可能的话,您可能更愿意将a,...,h中的任何一个或全部溢出,而不是r.

对于20世纪70年代或80年代的编译器来说,这是合理的.另一方面,现代优化编译器将拥有复杂的启发式算法来决定如何分配寄存器,在许多情况下,这些启发式算法比程序员的假设更准确.因此,现代编译器更有可能完全依赖自己的算法,而忽略register提示.

The "entry in a symbol table" remark might be from the same source (Expert C Programming - Deep C Secrets) as mentioned in Why is the 'auto' keyword useful for compiler writers in C?. It is not very clearly worded. The only sense I can make of it is that the compiler does need to keep track of which storage class specifiers were used to declare an object, e.g. to issue required diagnostics as noted above. So whatever data structure you use to associate the name and type of an object will need to have a flag to indicate if it was declared register, and that may be what they mean by "symbol table".

C++相关问答推荐

海湾合作委员会是否保证大小匹配的访问?

如何避免重新分配指针数组时,我们从一开始就不知道确切的大小

两个连续的语句是否按顺序排列?

GCC引发不明确的诊断消息

以前版本的tty_ldisc_ops.ioctl()是否也需要文件参数?

为什么在函数内部分配内存空间时需要添加符号?

将fget()与strcMP()一起使用不是正确的比较

在C语言中,在数学运算过程中,为什么浮点数在变量中的行为不同

试图从CSV文件中获取双精度值,但在C++中始终为空

`#if`条件中是否允许`sizeof`?

平均程序编译,但结果不好

Kdb:仅升级指定的列

为什么我的Hello World EFI程序构建不正确?

指向不同类型的指针是否与公共初始序列规则匹配?

向左移位3如何得到以字节为单位的位数?

C语言中的指针和多维数组

令人困惑的返回和 scanf 问题相关

无法理解 fgets 输出

C 语言中霍尔分区的快速排序算法

可以从指针数组中的值初始化指针吗?