对于嵌入式SW项目,我们需要使用一些const volatile TYPE *
指针。现在我们有一些计算函数,如下所示:
uint8 calc(const volatile uint8 *array, uint8 value) { ... }
在功能执行期间,两个变量的数据都没有变化。
调用代码如下所示:
const volatile uint8 *array = (const volatile uint8 *)0x00010111;
uint8 value = 8;
uint8 result = calc(array, value);
现在的问题是,如果我们设计没有volatile参数的calucation函数会有区别:
uint8 calc(const uint8 *array, uint8 value) { ... }
对于这个电话,我们抛弃了volatile:
uint8 result = calc((const uint8 *)array, value);
第二种解决方案的优点是更灵活:我们也可以将该函数用于非易失性变量。但它是否有所作为,如果我们抛弃volatile并且我们的编译器做了一些强有力的优化?
答案 0 :(得分:3)
您可以始终将该函数与非易失性参数一起使用。它只是函数中的代码处理给定的对象,就像它们是易失性的一样(最有可能在路上失去性能)。有点难以想象具有易失性参数的函数(“因为它们可能会在没有通知的情况下发生变化”)可以明智地做到。在您编写时,在您的情况下数据不会发生任何变化,因此最灵活的解决方案是声明参数const并忘记volatile。
请相当,请使用“uint8_t”而不是像uint8这样的本土类型名称 - 自1996年以来它就是标准!
答案 1 :(得分:1)
有两种情况:函数是直接操作硬件寄存器等。然后你必须在参数中有volatile。或者该功能与硬件寄存器完全无关。然后它不应该有volatile。这两种情况之间没有中间立场。
此外,calc((const uint8_t*)array, value);
只是一个糟糕的,可能是错误的
const uint8_t* ptr = array;
calc(ptr, value);
前一种形式很糟糕,因为函数参数的评估顺序是未指定的行为。编译器可能首先选择评估左操作数或右操作数,并且您无法知道或承担订单。由于访问volatile是一种副作用,因此每次构建程序时,原始代码都可以提供不同的结果。这在实时嵌入式系统中尤其成问题(并且可能是危险的)。
因此,建议不要在表达式中访问volatile变量(参见MISRA-C:2004 12.2)。
答案 2 :(得分:0)
这取决于volatile
- ness。
如果在执行函数期间此数组中的值发生更改并且应注意这些更改,请将它们设为volatile
。
如果无关紧要,或者“旧”值更重要,请省略volatile
。