(v)实际上是(*& v),因为什么时候?

时间:2017-06-22 07:41:50

标签: c++ c++11 c++14 c++17

C ++标准专家能不能启发我:

由于(v)似乎等同于(*&v),因此哪个C ++标准版本的语句失败?

即。例如代码:

 #define DEC(V) ( ((V)>0)? ((V)-=1) : 0 )
 ...{...
        register int v=1;
        int r = DEC(v) ;
 ...}...

现在会在-std=c++17下生成警告,如:

  

不能取寄存器变量的地址

     

操作数的左侧必须是左值

许多C宏将括号中的所有宏参数括起来,其中上述仅仅是一个代表性的例子。

例如,产生警告的实际宏 RTA_*中的/usr/include/linux/rtnetlink.h个宏。

如果没有在C ++中使用/重新定义这些宏,是否有任何解决方法?

3 个答案:

答案 0 :(得分:16)

如果您查看最新C ++ 1z草案的修订摘要,您会在[diff.cpp14.dcl.dcl]

中看到这一点。
  

[dcl.stc]
  更改:删除寄存器存储类说明符   理由:以后启用已弃用关键字的重新调整用途   本国际标准的修订   对原始功能的影响:使用该寄存器的有效C ++ 2014声明   存储类说明符在本国际标准中不正确。   可以简单地删除说明符以保留原始含义。

警告可能是由于此。

答案 1 :(得分:13)

register不再是存储类说明符,您应该删除它。编译器可能没有发出正确的错误或警告,但您的代码不应该以{{1​​}}开头

以下是标准的引用,告知人们他们应该在代码中对register做些什么(相关部分强调),你可能有该文件的旧版本

C.1.6第10条:声明[diff.dcl]

  

更改:在C ++中,register不是存储类说明符。

     

基本原理:存储类说明符对C ++没有影响。   对原始特征的影响:删除语义明确定义的特征。

     

难以转换:语法转换。

     

使用范围广泛:普通。

答案 2 :(得分:6)

您的担心是没有根据的,因为相关文件实际上并不包含register关键字:

grep "register" /usr/include/linux/rtnetlink.h

什么都不输出。无论哪种方式,您都不应该收到警告:

  • 默认情况下,系统标头不会发出警告,至少在GCC中

  • 在C ++模式下尝试编译属于Linux内核等系统项目的文件是不明智的,因为可能存在微妙且令人讨厌的重大变化

只需正常包含文件或将C代码链接到C ++二进制文件即可。如果您确实收到通常应该被抑制到编译器供应商的警告,请报告错误。