web-dev-qa-db-ja.com

`void`へのキャストは本当に何をしますか?

_(void)x;_のようなよく使用されるステートメントにより、未使用の変数xに関する警告を抑制することができます。しかし、次をコンパイルしようとすると、よくわからない結果が得られます。

_int main()
{
    int x;
    (short)x;
    (void)x;
    (int)x;
}
_

これをg ++でコンパイルすると、次の警告が表示されます。

_$ g++ test.cpp -Wall -Wextra -o test
test.cpp: In function ‘int main()’:
test.cpp:4:13: warning: statement has no effect [-Wunused-value]
     (short)x;
             ^
test.cpp:6:11: warning: statement has no effect [-Wunused-value]
     (int)x;
           ^
_

したがって、voidへのキャストは、他の型へのキャストとは非常に異なり、ターゲットの型はdecltype(x)と同じか、何か違うと結論付けます。考えられる説明に対する私の推測は次のとおりです。

  • _(void)x;_だけの規則ですが、他のキャストでは警告を抑制しません。すべてのステートメントは同様に効果がありません。
  • この違いは、_void x;_が有効なステートメントであるのに対し、_short x;_は有効なステートメントではないという事実に何らかの関係があります。

これらのどれがより正確であるか?ない場合、コンパイラ警告の違いはどのように説明できますか?

29
Ruslan

Voidへのキャストは、コンパイラの警告を抑制するために使用されます。 標準 §5.2.9/ 4には、

どの式も明示的に「cv void」型に変換できます。式の値は破棄されます。

32
Rahul Tripathi

この文:

(void)x;

「xの値を無視する」と言います。 voidなどのタイプはありません-タイプがありません。したがって、これとは非常に異なります。

(int)x;

「整数xとして扱うx」結果の整数が無視されると、警告が表示されます(有効になっている場合)。

何もないものを無視する場合、GCCによって問題とは見なされません。また、CおよびC++で明示的に変数を無視する慣用的な方法であるvoidへのキャストであるため、正当な理由があります。

11
John Zwinck

標準では、未使用のローカル変数または関数パラメーターに対して警告(標準では「診断」)を生成することは義務付けられていません。同様に、このような警告がどのように抑制されるかは強制されません。この警告を抑制するために変数式をvoidにキャストすることは、結果がどのような方法でも使用できないため(たとえば(int)x以外)、代わりにC以降のC++コミュニティでイディオムになりました。対応するコードが欠落しているだけです。例えば。:

(int)x;  // maybe you meant f((int)x);
(void)x; // cannot have intended f((void)x);
(void)x; // but remote possibility: f((void*)x);

個人的には、この規則はまだあいまいすぎると思うので、関数テンプレートを使用したいのです。

template<typename T>
inline void ignore(const T&) {} // e.g. ignore(x);

ただし、関数パラメーターを無視する慣用的な方法は、名前を省略することです(上記参照)。この関数を頻繁に使用するのは、assertなどの条件付きでコンパイルされたコードで関数パラメーターに名前を付ける必要がある場合です。私は見つけます#ifdef NDEBUGの使用よりも読みやすい次の:

void rate(bool fantastic)
{
    assert(fantastic);
    ignore(fantastic);
}
4
Arne Vogel

可能な用途:

auto it = list_.before_begin();
for (auto& entry : list_)
{
    (void)entry; //suppress warning
    ++it;
}

反復子「it」は最後の要素を指します

0
Traummaennlein