为什么创build了register关键字?

在阅读Herb Sutter的 关键词“不是(或者 别名 )”的时候 ,我遇到了这样几句话:

没错,有些关键字在语义上等同于空白,一个美化的评论。

我们已经看到了为什么C ++语言把关键字当作保留字,并且我们看到了两个关键字-auto和register–它们与C ++程序没有任何语义上的区别。 不要使用它们; 无论如何,它们只是空白的,有更快的方法来input空格。

如果像auto这样的关键字(可能不在C ++ 11中)和register是没有价值的,那他们为什么创build和使用?

如果在variables之前包含register没有任何区别

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

为什么上面的程序出错?

test_register.c:在函数'main'中:

test_register.c:4:2:错误:请求寄存器variables'a'的地址

的printf( “%d \ n%d \ n”,&A,A);

以下程序在C ++中工作。

 #include<iostream> int main(){ register int a = 15; std::cout<<&a<<'\n'<<a; return 0; } 

寄存器

在C中, register存储类被用作编译器的提示,表示variables应该优先存储在寄存器中 。 请注意,将registervariables存储在实际寄存器中的提示可能会也可能不会被遵守,但在任何情况下,相关限制仍然适用。 见C11,6.7.1p6(重点是我的):

具有存储类说明符register的对象的标识符声明表明对该对象的访问尽可能快。 这些build议的有效程度是由实施定义的。 [脚注121]

[脚注121]该实现可以将任何register声明简单地视为auto声明。 但是,实际上是否使用可寻址存储,使用存储类说明符register声明的对象的任何部分的地址都不能被明确地(通过使用6.5.3.2中讨论的一元&运算符)或隐式地通过将数组名称转换为指针,如6.3.2.1)所述。 因此,可以应用于使用存储类说明符register声明的数组的唯一运算符是sizeof_Alignof

在C ++中,它仅仅是一个未使用的保留关键字,但是假设它保持与C代码的语法兼容性是合理的。

汽车

在C中, auto存储类定义了一个自动存储的variables,但通常不会使用,因为默认情况下函数局部variables是auto的 。

类似地,假设它最初仅仅是为了语法兼容性而被转移到C ++是合理的,尽pipe后来它得到了自己的意义( types推断 )。

在C register服务有两个目的:

  • 提示编译器该variables应该存储在一个寄存器中以获得性能。 这个用途现在已经大大过时了。
  • 防止程序员使用variables,以防止它被存储在寄存器中。 这种使用只是有点过时的国际海事组织。

这和const类似,哪个

  • 向编译器提示variables可以存储在只读存储器中。
  • 防止程序员写入variables

作为一个例子,考虑这个简单的function:

 int sum(const int *values, size_t length) { register int acc = 0; for (size_t i = 0; i < length; ++i) { acc += values[i]; } return acc; } 

程序员写了一个register来保持累加器不在堆栈中,每次更新时都避免写一个内存。 如果实现得到改变,如下所示:

 // Defined in some other translation unit void add(int *dest, int src); int sum(const int *values, size_t length) { register int acc = 0; for (size_t i = 0; i < length; ++i) { add(&acc, values[i]); } return acc; } 

由于寄存器没有地址,因此accvariables在add()调用时不能再存储在寄存器中。 因此,编译器会将&acc标记为错误,让您知道您可能已经通过阻止acc生存在寄存器中来破坏您的代码的性能。

在编译器变得笨拙的时代,variables在整个函数中只能存在一个地方,这在以前变得更加重要。 现在,一个variables的大部分时间都可以在寄存器中使用,只有当地址被占用时才会被暂时移到栈上。 就是这个代码:

 /* Passed by reference for some reason. */ void debug(const int *value); int sum(const int *values, size_t length) { int acc = 0; for (size_t i = 0; i < length; ++i) { acc += values[i]; } debug(&acc); return acc; } 

会导致acc在旧的编译器中为整个函数生活在栈上。 现在的编译器会在调用debug()之前保持acc在寄存器中。

现代C代码通常不使用register关键字。

C99理由提供了更多的关键字register上下文:

国际标准的理由 – 编程语言 – C

§6.7.1存储类说明符

由于registervariables的地址不能被采用,因此存储类register对象有效地存在于与其他对象不同的空间中。 (函数占用了第三个地址空间。)这使得它们成为最佳布局的候选对象,这是声明寄存器的通常原因; 但它也使得他们成为更积极的优化的候选人。