寄存器const变量将存储在哪里?

时间:2015-01-31 09:20:43

标签: c compiler-construction const cpu-registers

我知道当变量声明在寄存器关键字编译器之前时,编译器可以将变量放在CPU的寄存器中以便更快地访问。同样的方式我知道编译器可以将 const 变量放在ROM中,因为const变量的值在整个程序执行期间不会发生变化。我也知道寄存器说明符是对将变量放入CPU寄存器的实现。但是如果变量将被标记为 const &的注册? 请考虑以下计划:

#include <stdio.h>
int main()
{
    register const int a=3;
    printf("%d",a);
    return 0;
}

在这种变量存储的情况下?在CPU寄存器或堆栈中(如果编译器忽略寄存器请求)或在编译器优化它时在ROM中。

2 个答案:

答案 0 :(得分:1)

首先,当您将变量声明为const时,编译器永远不会将其放入ROM中,因为......编译器,链接器和后来的加载器都不能在ROM中写入任何内容!它只能将它放在仍然驻留在RAM中的只读段中,即使运行时的任何写访问都会导致错误。

然后,为了更准确地回答您的问题,编译器可能总是按照自己的意愿行事。

  • 当您声明变量const时,编译器 如果检测到更改则会抛出错误,可以将其置于只读段< / LI>
  • 当您声明变量register时,编译器应该如果它检测到尝试获取其地址则抛出错误,并且可以尝试保留它在注册。

唯一明确要求的是编译器正确处理正确的代码。如果无法编译某些代码,则会要求抛出错误,但允许接受错误的代码:可能称为扩展或特殊功能。例如,编译器可以自由声明它完全忽略register声明并允许获取register变量的地址,但必须至少发出警告[编辑见下文详情]。只需不得阻塞正确的register(或const用法)。

可以使用registerconst声明进行优化,但可以完全自由地忽略它们。例如,以下代码:

const int a = 5;
const int *b = (int *) &a;
*b = 4;

导致未定义的行为。如果在那之后它依赖于实现:

  • a = 5
  • a = 4
  • 程序崩溃
  • 计算机被点燃了(但这个应该是不常见的:-))
  • ...

编辑:

JensGustedt在评论中指出,C语言规范包含段落 6.5.3.2地址和间接运算符这个约束子句:

一元&amp;的操作数运算符应该......,或指定不是位字段的对象的左值,并且未使用寄存器存储类说明符声明。(强调我的)

在约束条款中,相同规范的段落 5.1.1.3诊断要求符合条件的实现应生成至少一条诊断消息(以实现定义的方式标识),如果预处理翻译单元或翻译单元包含违反任何语法规则或约束。

因此,如果程序员试图获取寄存器变量的地址,那么符合标准的C编译器必须至少发出警告。

答案 1 :(得分:1)

我实际上知道知道在这种情况下单个编译器做了什么,但是从逻辑开始,并且假设register更多是建议,并且编译器是允许的为了忽略它,就标准而言,我说有三种可能的结果:

  1. 由于常量通常很有效,并且通常可以作为指令的一部分进行编码或优化,因此甚至可能不需要从数据部分明确地加载到寄存器中,它可能只是忽略了完全register个关键字,并将其视为const

  2. 如果有任何代码生成步骤需要决定将哪些值放入寄存器以及其他地方,并且a是这些值之一,编译器可能会考虑您声明它作为register并且更喜欢。

  3. (这可能仅仅是#2的变体)编译器可能会决定您有理由在此指定register并始终强制a进入寄存器。最糟糕的情况是,这可能与优化器通常如何将代码分配给寄存器有关,并且可能导致次优代码。或者如果您真的知道自己在做什么,它可能会解决优化器错误。