const volatile指针函数参数

对于嵌入式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) { ... } 

对于电话,我们抛弃了波动:

 uint8 result = calc((const uint8 *)array, value); 

第二种解决方案的优点是更灵活:我们也可以将该函数用于非易失性变量。 但它是否有所作为,如果我们抛弃volatile并且我们的编译器做了一些强有力的优化?

您始终可以将该函数与非易失性参数一起使用。 它只是函数中的代码处理给定的对象,就好像它们是易失性的一样(很可能在途中失去性能)。 有点难以想象具有易失性参数的函数(“因为它们可能会在没有通知的情况下发生变化”)可以明智地做到。 在您编写时,在您的情况下数据不会发生任何变化,因此最灵活的解决方案是声明参数const并忘记volatile。

请相信,使用“uint8_t”而不是像uint8这样的本土类型名称 – 自1996年以来它就是标准!

有两种情况:function是直接操作硬件寄存器等。 然后你必须在参数中有volatile。 或者该function与硬件寄存器完全无关。 然后它不应该有挥发性。 这两种情况之间没有中间立场。

此外, calc((const uint8_t*)array, value); 只是一个糟糕的,可能是错误的版本

 const uint8_t* ptr = array; calc(ptr, value); 

前一种forms很糟糕,因为函数参数的评估顺序是未指定的行为。 编译器可能首先选择评估左操作数或右操作数,并且您无法知道或承担订单。 由于访问volatile是一种副作用,因此每次构建程序时,原始代码都会产生不同的结果。 这在实时嵌入式系统中尤其成问题(并且可能是危险的)。

因此,建议不要访问表达式中的volatile变量(参见MISRA-C:2004 12.2)。

这取决于由于volatile而真正发生的事情。

如果在执行函数期间此数组中的值发生更改并且应注意这些更改,请将它们设置为volatile

如果无关紧要,或者“旧”值更重要,则省略volatile