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,他们希望停止对纯函数的重复调用的优化? 函数内部的静态变量的增量将解决它。 但是,试着猜测它们的初衷,因为这没有任何意义。