关于C和C++的register关键字

关于C和C++的register关键字


近日看到一些C++代码在for循环里加入了register关键字来试图声明寄存器变量,并声称可以优化速度,那么这是不是有效的呢?我们将看到,这个写法在C语言里也许(但未必)是有效的,但是在C++语言里可能不是非常有效了。

In C++

博主在写这篇博客的时候最新C++标准是ISO/IEC 14882:2017,C++20目前只出了一个working draft,还没有出台出现正式的文件,因此我们以C++17为最新标准。
我们翻开C++17标准,里面有类似的叙述:

第C.1.6款:

Change: In C++, register is not a storage class specifier.
Rationale: The storage class specifier had no effect in C++.

第C.4.3款:

Change: Removal of register storage-class-specifier.
Rationale: Enable repurposing of deprecated keyword in future revisions of this International Standard.
Effect on original feature: A valid C++ 2014 declaration utilizing the register storage-class-specifier is ill-formed in this International Standard . The specifier can simply be removed to retain the original meaning.

C++17标准很明确地指出,register关键字在C++17已经是一个没有任何作用(“no effect”)的关键字了,带有register存储类型标识符的程序已经是"ill formed"的了。因此我们不应该再写register关键字来声明寄存器变量。

实际上,register关键字在稍老的C++标准中也不总是有效。我们翻开最古老的C++98标准,其中的第7.1.1款第4条是这样描述register关键字的:

A register specifier has the same semantics an auto specifier together with a hint to the implementation that the object so declared will be heavily used. [Note: the hint can be ignored and in most implementations it will be ignored if the address of the object is taken. —end note]

这句话的大概意思就是,register关键字和auto关键字在语义上是一样的(博主注:在C++98标准中auto并没有类型自动推导的作用,它的作用仍然和C语言一样是自动存储类型的意思),只是暗示了这个变量可能会被频繁使用,而且regester关键字起不起作用还要看编译器愿不愿意理它,并且大部分情况下都不愿意理它,而且你如果想对register变量取地址,那么这个关键字就一定会不起作用。这样看来即使在旧的C++标准中regester关键字的作用也不是特别大。
实际上,编译器的优化能力是非常强的,会自动帮助做很多优化,大多数时候并没有必要自己加上register关键字来提示编译器来把它优化成寄存器变量,这个优化编译器多数时候会直接做的。因此C++17标准索性删除了register关键字的用法也就不奇怪了(不过这个关键字本身还是被保留了下来)。
总之,在现代C++中,再使用register关键字声明寄存器变量已经是不合标准的了,我们应该避免做这种事情。

In C

与之形成对比的是C语言。C语言的最新标准目前是ISO/IEC 9899:2018。不过这一标准相对于上衣标准C11改动不大,因此我们查看C11标准也不是问题。
其实在C语言中对register变量做的约束就非常大了,不过我们将会看到实际上这也只是语法上的约束,实际的作用可能不如人意。
在6.7.1的第6条正文和注121中这样写道:

6 A declaration of an identifier for an object with storage-class specifier register suggests that access to the object be as fast as possible. The extent to which such suggestions are effective is implementation-defined.121)

121) The implementation may treat any register declaration simply as an auto declaration. However, whether or not addressable storage is actually used, the address of any part of an object declared with storage-class specifier register cannot be computed, either explicitly (by use of the unary & operator as discussed in 6.5.3.2) or implicitly (by converting an array name to a pointer as discussed in 6.3.2.1). Thus, the only operator that can be applied to an array declared with storage-class specifier register is sizeof.

上面的两段话大致意思是,register关键字暗示编译器对这个变量的访问应该尽可能地快.至于这样的 暗示是否有效则是编译器自行决定的。register关键字可以被简单地当作auto对待。然而,不管这个关键字是否有效,我们都不能显式或隐式地取它的地址。
这很好理解,因为我们是要把这个变量声明为寄存器变量的,而寄存器不在内存中,自然是没有地址的。不过这仅仅是一个语法上的 约束,正如之前所说,这个关键字是否实际起作用还需要视编译器而定。在一些情况下,register会退化成auto
这样看来,register关键字在C语言中可能会有用处,但实际上用处可能并不是那么大。正如我们之前所说,在一些情况下,编译器会自动帮助我们优化这些变量。

结论

总之,现在再去写register关键字已经没有太大的必要了,如果你是在一些编译器版本比较古老的并且不开优化的OJ平台上进行算法竞赛也许是需要节省这样的常数时间的,但是我们在现代的开发中并没有写它的必要,在C++17标准中也不能写上它。

参考文献

  1. ISO/IEC 9899:2011, Information Technology — Programming languages — C
  2. ISO/IEC 14882:1998, Programming languages — C++
  3. ISO/IEC 14882:2017, Programming languages — C++
<think>嗯,用户想知道C++register关键字的作用用法。首先,我需要回顾一下register关键字的历史演变。记得在早期的C语言中,register用来建议编译器将变量存储在寄存器中,以提升访问速度。后来C++继承了这一点,但在C++11之后,这个关键字被弃用了,到C++17可能就完全移除了。 接下来,要解释register的功能。主要是在声明变量时建议编译器将其存储在寄存器中,而不是内存里。不过,编译器可能会忽略这个建议,特别是现代编译器优化已经很智能,能够自动决定哪些变量放在寄存器中更有效率。所以实际上,register可能对性能影响不大,甚至没有影响。 然后,使用场景方面,可能是在需要频繁访问的变量,比如循环计数器或者临时变量,才考虑使用register。但要注意,无法获取register变量的地址,因为寄存器没有内存地址。这也是为什么像int *p = &a;这样的代码如果a是register变量就会报错。 现在要确保回答的结构清晰,先讲功能,再讲用法,然后是注意事项现状。还要注意用户提到的引用格式,不过用户提供的引用内容似乎register关键字无关,可能是个错误。所以可能不需要引用这些内容,或者需要检查是否有相关的引用资料被误贴了。 最后,生成相关问题的时候,可以考虑register关键字的演变、与现代auto关键字的区别、被弃用的原因,以及替代方法等。确保问题有针对性,帮助用户深入理解。</think>### C++中`register`关键字的作用与用法解析 #### 1. **功能解释** - **寄存器变量建议**:`register`关键字用于向编译器**建议**将变量存储在寄存器中,而非内存。寄存器访问速度远快于内存,适用于高频访问的变量,例如循环计数器[^1]。 ```cpp register int counter; // 建议将counter放入寄存器 ``` - **限制**:`register`变量**不可取地址**(如`&counter`会报错),因为寄存器没有内存地址。 #### 2. **使用场景** - **高频访问的局部变量**:例如循环中的临时变量或计数器。 ```cpp for (register int i = 0; i < 1000000; ++i) { // 高频操作 } ``` - **编译器优化辅助**:早期用于手动优化性能,但现代编译器已能自动优化寄存器分配[^1]。 #### 3. **注意事项** - **编译器可能忽略建议**:是否真正使用寄存器由编译器决定,且现代优化器通常更高效。 - **C++标准演变**: - **C++11起弃用**:因编译器优化能力增强,`register`逐渐失去实际意义。 - **C++17移除**:不再作为关键字存在,代码中使用会导致编译错误。 #### 4. **现状与替代** - **依赖编译器优化**:无需手动指定,编译器通过分析代码自动分配寄存器。 - **替代方案**:使用`auto`关键字C++11起)推导变量类型,同时编译器仍可能优化其存储位置。 --- ###
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值