volatile变量作为函数的参数

有这个代码:

typedef volatile int COUNT; COUNT functionOne( COUNT *number ); int functionTwo( int *number ); 

我无法摆脱一些警告..

我在functionOne原型上得到了这个警告1

函数返回类型时忽略[警告]类型限定符

我得到这个警告2,无论我用一个COUNT 指针参数而不是一个int指针调用functionTwo

[警告]从指针目标类型中抛弃限定符

显然变量/指针不能“强制转换”为volatile / un-volatile ..但是每个参数都必须指定为volatile吗? 那么如果已经为非易失性变量定义了库函数怎么用呢?

编辑 :使用gcc -std=c99 -pedantic -Wall -Wshadow -Wpointer-arith -Wcast-qual -Wextra -Wstrict-prototypes -Wmissing-prototypes …

编辑 :在Jukka Suomela建议之后,这是警告二的代码示例

 typedef volatile int COUNT; static int functionTwo(int *number) { return *number + 1; } int main(void) { COUNT count= 10; count = functionTwo(&count); return 0; } 

volatile关键字旨在应用于表示存储而不是函数的对象。 从函数返回volatile int没有多大意义。 函数的返回值将不会被优化掉(内联函数可能除外,但这是另一种情况……),并且没有外部actor会修改它。 当函数返回时,它将返回值的副本传递给调用函数。 volatile对象的副本本身volatile 。 因此,尝试返回volatile int将导致复制,将其转换为非易失性int ,这是触发编译器消息的原因。 返回volatile int*可能很有用,但不是volatile int

将按值传递给函数会生成对象的副本,因此使用volatile int作为函数参数必然会涉及忽略限定符的转换。 通过地址传递易失性是完全合理的,但不是价值。

根据C规范, volatile的行为完全依赖于实现,因此YMMV。

您是否以这种方式使用volatile来尝试打败某种编译器优化? 如果是这样,可能有更好的方法。

编辑:考虑到您的问题的更新,您似乎可以以不同的方式处理此问题。 如果你试图打败编译器优化,为什么不采取直接的方法,只是告诉编译器不优化一些东西? 您可以使用#pragma GCC optimize__attribute__((optimize))为函数提供特定的优化参数。 例如, __attribute__((optimize(0)))应禁用给定函数的所有优化。 这样,您可以使数据类型保持非易失性并避免出现类型问题。 如果禁用所有优化有点过多,您还可以使用该属性/ pragma打开或关闭各个优化选项。

编辑:我能够编译以下代码,没有任何警告或错误:

 static int functionTwo(int *number) { return *number + 1; } typedef union { int i; volatile int v; } fancy_int; int main(void) { fancy_int count; count.v = 10; count.v = functionTwo(&count.i); return 0; } 

这种黑客 “技术”可能有一些奇怪的副作用,所以在生产使用之前要彻底测试。 将地址直接转换为(int*)很可能没有什么不同,但它不会触发任何警告。

我可能会离开这里,但是volatile不是通常与堆栈内存区域相关的东西。 因此,我不确定以下原型是否真的有意义。

 volatile int functionOne(volatile int number); 

我不确定返回的整数是如何变量的。 什么会导致EAX的价值发生变化? 这同样适用于整数。 一旦将值压入堆栈,以便它可以作为参数传递什么将改变其值?

我不明白你为什么要在函数返回类型上使用volatile限定符。 您为函数的返回值赋值的变量应该键入为volatile

尝试进行以下更改:

 typedef int COUNT_TYPE; typedef volatile COUNT_TYPE COUNT; COUNT_TYPE functionOne( COUNT number ); COUNT_TYPE functionTwo( COUNT_TYPE number ); 

在调用functionTwo() ,显式地转换参数:

 functionTwo( (COUNT_TYPE)arg ); 

HTH,Ashish。

如果我编译

 typedef volatile int COUNT; static int functionTwo(int number) { return number + 1; } int main(void) { COUNT count = 10; count = functionTwo(count); return 0; } 

运用

 gcc -std=c99 -pedantic -Wall -Wshadow -Wpointer-arith -Wcast-qual \ -Wextra -Wstrict-prototypes -Wmissing-prototypes foo.c 

我没有收到任何警告。 我尝试了gcc 4.0,4.2,4.3和4.4。 你的警告两个听起来像是在传递指针 ,而不是价值观,这是另一个故事……

编辑:

你的最新例子应该是这样写的; 再次,没有警告:

 typedef volatile int COUNT; static int functionTwo(COUNT *number) { return *number + 1; } int main(void) { COUNT count = 10; count = functionTwo(&count); return 0; } 

编辑:

如果你不能改变function2:

 typedef volatile int COUNT; static int functionTwo(int *number) { return *number + 1; } int main(void) { COUNT count= 10; int countcopy = count; count = functionTwo(&countcopy); return 0; } 

请注意,对volatile变量的任何访问都是“特殊的”。 在带有functionTwo(COUNT *number)的第一个版本中,functionTwo知道如何正确访问它。 在带有countcopy的第二个版本中,main函数知道在分配countcopy = copy时如何正确访问它。

编写它的人可能希望确保所有操作都是primefaces操作,并将所有int变量声明为volatile(这是一个同步不良的MT应用程序吗?),因此代码中的所有int都被声明为volatile“for一致性”。

或者也许通过将函数类型声明为volatile,他们希望停止对纯函数的重复调用的优化? 函数内部的静态变量的增量将解决它。 但是,试着猜测它们的初衷,因为这没有任何意义。