web-dev-qa-db-ja.com

(v)は実際には(*&v)いつからですか?

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_*マクロin/usr/include/linux/rtnetlink.hです。

C++でこれらのマクロを使用/再定義しない以外に、回避策はありますか?

17
JVD

最新のC++ 1zドラフトのリビジョンの概要を見ると、これは [diff.cpp14.dcl.dcl] にあります。

[dcl.stc]
変更:レジスタstorage-class-specifierの削除。
根拠:この国際規格の将来の改訂で非推奨のキーワードの転用を有効にします。
元の機能への影響:レジスタstorage-class-specifierを使用する有効なC++ 2014宣言は、この国際標準では不正な形式です。指定子は、元の意味を保持するために簡単に削除できます。

警告はそれが原因である可能性があります。

registerはストレージクラス指定子ではなくなったため、削除する必要があります。コンパイラは正しいエラーや警告を発行していない可能性がありますが、コードの先頭にregisterを含めることはできません。

以下は、コード内のregisterに関して何をすべきかを人々に知らせる標準からの引用です(関連部分が強調されています)、おそらくそのファイルの古いバージョンがあります

C.1.6条項10:宣言[diff.dcl]

変更:C++では、レジスターはストレージクラス指定子ではありません。

理論的根拠:ストレージクラス指定子はC++では効果がありませんでした。元の機能への影響:意味的に明確に定義された機能の削除。

変換の難しさ:構文変換。

広く使用されている方法:一般的。

13
Curious

問題のファイルには実際にはregisterキーワードが含まれていないため、心配する必要はありません。

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

何も出力しません。いずれにせよ、次の理由で警告を受け取るべきではありません。

  • 少なくともGCCでは、システムヘッダーはデフォルトで警告を発しません

  • 微妙で厄介な重大な変更がある可能性があるため、Linuxカーネルのようなシステムプロジェクトに属するファイルをC++モードでコンパイルしようとするのは賢明ではありません。

通常どおりファイルを含めるか、CコードをC++バイナリにリンクします。通常はコンパイラベンダーに抑制すべき警告が実際に表示される場合は、バグを報告してください。

6
user141770