两种情况:
返回静态volatile变量
直接访问易变变量
Q1:函数调用的赋值是否与直接从volatile变量赋值的行为不同?
Q2:如果有,是否有通过函数返回访问volatile的标准方法?
/*timer.h*/
extern volatile uint8_t directFlag;
uint8_t getReturnFlag(void);
/*timer.c*/
volatile uint8_t directFlag = 0;
static volatile uint8_t returnFlag = 0;
uint8_t getReturnFlag(void)
{
return returnFlag;
}
void timerISR(void)
{
directFlag++;
returnFlag++;
}
/*main.c*/
#include "timer.h"
void main()
{
uint8_t a = 0;
uint8_t b = 0;
while(1)
{
a = directFlag;
b = getReturnFlag(); /* Can this be optimized out? */
}
}
答案 0 :(得分:2)
在您的代码中,几乎没有任何东西可以通过普通编译器进行优化。在编译main.c
时,编译器会看到一个函数调用(getReturnFlag()
),它无法知道它包含哪些可能的副作用,即使它知道它,也可以访问volatile变量
出于同样的原因(访问volatile变量是副作用),无法优化对directFlag
变量的访问。
但a
和b
变量的值从未在main.c
中使用,因此两者都可以进行优化。代码等同于:
#include "timer.h"
void main()
{
while(1)
{
(void) directFlag;
(void) getReturnFlag(); /* Can this be optimized out? */
}
}
无关:void main()
只能在独立环境中接受,我认为这是 embedded 标记所隐含的。
现在提出您的问题:
函数调用的赋值是否与直接从volatile变量赋值的行为不同?
访问volatile变量是明显的副作用,因此需要符合要求的实现来评估它。函数调用包含潜在的副作用,因为常见的实现分别编译不同的翻译单元,无法猜测是否会有副作用。但是如果函数的定义在同一个翻译单元中,并且实现可以推断出没有副作用(这里不是这种情况),它可能无法评估它
如果是这样,是否有通过函数返回访问volatile的标准方法?
只有实现(编译器)可以推断出没有产生副作用时,才能消除函数调用。如果函数访问volatile,那么符合条件的编译器就不能消除它