如何消除“discard qualifier”警告?

6

使用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 *)类型转换来消除它,但这在代码中的许多地方都会重复出现。

有没有一种方法可以通过选项或编译指示(或等效物)消除此特定警告?

2个回答

4

不,你不能关闭那个警告。它是在告诉你违反了类型系统。如果你想调用func,你需要传递指向非易失性数据的指针或更改函数签名以接受指向易失性数据的指针。


2
谢谢。这实际上很有趣(在某种程度上也是有争议的)。我并不真正改变变量的类型volatile限定符是优化器的信号。所以我想知道为什么它被认为是违反类型系统的?! - ysap
1
const int*传递给函数func(int*)与类型系统不符,同样的道理。 - Jonathan Wakely
1
@ysap volatile,就像 const 一样,是类型的一部分。 - rubenvb
2
@rubenvb,Jonathan - 在接受您的评论时,我确实看到了“const”和“volatile”限定符之间的区别。据我理解,“const”限定符提供有关对象的编译时(而不是优化时)信息。例如,它应该防止我将值分配给该对象,并且如果我尝试这样做,我应该得到诊断。对于易失性变量,没有这样的问题(我现在能想象到)。 - ysap
1
但是,当你仔细思考时,问题可能在于编译器防止将易失性对象传递给非易失性函数,并且该函数具有非易失性参数,*被过度优化到了结果不正确的程度,因为它与易失性对象相关! - ysap
显示剩余5条评论

1
标准允许编译器在使用非限定指针访问volatile限定对象时进行任何操作。这允许在某些平台上,某些volatile限定对象可能需要特殊指令才能访问,例如,通过volatile uint16_t*写入可能会生成等效于以下代码的代码:
if ((uintptr_t)ptr >= 0xFFFF0000)
  __outport16(0xFFFF & (uintptr_t)ptr, value);
else
  (uint16_t*)ptr = value;

如果编译器作者认为编译器只能在不常用的平台上利用这些自由,否则代价太高,并且在成本几乎为零的平台上提供明智的行为,而原始示例中的调用代码知道在执行func期间没有外部实体将访问Y,则针对该编译器的代码将能够通过将Y的地址转换为float*来实现所需的行为,而无需诊断。不幸的是,维护gcc和clang的人似乎认为当标准引用“非可移植或错误的构造”时,它实际上意味着“非可移植,即错误的构造”,而不是“构造物并非适用于每个符合标准的机器,如果有意进行这种可移植性,则会出错”。将指针强制转换为float*将消除gcc或clang上的警告,但我不确定它会导致它们产生明智的代码。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接