5

GCCおよびC99モードを使用して、次のように宣言された関数があります。

void func(float *X);

関数を呼び出すときは、揮発性配列Yを使用します。

volatile float Y[2];
int main()
{
    func(Y);
    return 0;
}

(を使用して)コンパイルすると-Wall、次の警告が表示されます。

warning: passing argument 1 of ‘func’ discards qualifiers from pointer target type
blah.c:4: note: expected ‘float *’ but argument is of type ‘volatile float *’

(float *)明示的な型キャストでそれを排除できますが、これはコードの多くの場所で繰り返されます。

オプションまたはプラグマ(または同等のもの)を使用して、この特定の警告を排除する方法はありますか?

4

2 に答える 2

4

いいえ、その警告をオフにすることはできません。型システムに違反していることを示しています。呼び出したい場合はfunc、不揮発性データへのポインターを渡すか、関数シグネチャを変更して揮発性データへのポインターを受け入れる必要があります。

于 2012-08-28T16:56:37.253 に答える
1

この標準では、修飾されていないポインタを使用して修飾されたvolatileオブジェクトにアクセスする場合、コンパイラは好きなことを行うことができます。これにより、一部のvolatile修飾オブジェクトがそれらにアクセスするために特別な命令を必要とする可能性があるプラットフォームが可能になります。たとえば、writeviaは次とvolatile uint16_t*同等のコードを生成する可能性があります。

if ((uintptr_t)ptr >= 0xFFFF0000)
  __outport16(0xFFFF & (uintptr_t)ptr, value);
else
  (uint16_t*)ptr = value;

コンパイラーの作成者が、コンパイラーがそのような自由を利用するのはあいまいなプラットフォームでのみ行うべきであるという態度をとる場合、そうでなければ費用がかかり、そうすることでほとんど費用がかからないプラットフォームで賢明な動作を提供する必要があり、元の例の呼び出しコードがそれを知っている場合のY実行中に外部エンティティがアクセスすることはありませんfunc。その場合、そのコンパイラを対象とするコードは、Yのアドレスをにキャストするだけで、診断なしで必要な動作を実現できます。float*。残念ながら、gccとclangを維持している人々は、標準が「移植性のない、または誤った構造」を指す場合、それは実際には「すべての人に移植可能ではない構造」ではなく「移植性のない、つまり誤った構造」を意味すると信じているようです。宇宙の適合マシンであり、そのような移植性が意図されている場合は誤りです。ポインタをキャストするfloat*と、gccまたはclangの警告が無音になりますが、それが適切なコードを生成することは期待できません。

于 2017-09-28T22:08:49.943 に答える