为什么在函数中丢弃volatile限定符会调用警告?

sap*_*api 11 c warnings volatile

(在我开始:我知道有存在的 问题在这个题目,但没有我发现答案,为什么这是一个问题,我经常这样做,并想知道如果我创造潜在的问题.)

我很好奇为什么在函数调用中丢弃volatile限定符需要编译器警告.

情况如下:

volatile uint8_t thingy;
void awesome_function(uint8_t *arg);

awesome_function(&thingy); << warning
Run Code Online (Sandbox Code Playgroud)

现在,我的理解是volatile限定符将变量标记为可能在编译器控件之外的方式发生变化的变量.因此禁用某些优化(最重要的是,根据我的经验,删除'未使用的'变量).

但是,如果我将变量标记为volatile,我担心在此范围内阻止优化.如果我将变量传递给函数,我通常很乐意在该函数中应用标准优化.*

即使编译器想要从函数中删除变量(我通常试图避免的优化),即使它这样做,也不会影响我在此范围内使用它; (函数的结果)函数本身就是我感兴趣的序列点(和左值).

那么,为什么放弃关于函数的限定符会调用警告,因为它不会在当前范围内启用重新排序?这是因为在被调用函数的范围内可能重新排序,这是不允许的volatile变量?如果是这样,为什么这是当前范围的问题?

(*这通常是因为这样的调用用于启动异步操作,最终将对传递给函数的指针进行操作.该函数可以使用指针执行任何操作,只要它最终根据请求更新它.volatile限定符在那里提醒编译器本地变量将异步更改.)

tem*_*def 23

这里的警告是因为编译器假设当你有一个指向volatile指针对象的指针时,你真的相信指针值可能会从外部源改变.当您将此指针传递给要求指向非volatile对象的指针的函数时,编译器会警告您,函数调用可能会以不能正确解释对象可能更改的方式进行优化.

事实上,你肯定知道这样做是可以的,这意味着你可能想要放入一个删除的显式强制转换volatile,例如:

awesome_function((uint8_t*) &thingy);
Run Code Online (Sandbox Code Playgroud)

这明确告诉编译器"我知道我要删除它volatile,所以不要警告我." 毕竟,警告的重点是你可能没有注意到这一点.

一个很好的类比就是要思考const.如果你有一个指向const对象的指针,你承诺不通过指针修改该对象.如果您尝试将此指针传递给一个带有指向非const对象的指针的函数,则会收到警告,因为编译器会注意到您可能会意外地通过该函数更改值.放入一个显式的强制转换将是一种告诉编译器的方法"是的,我知道这个指针不应该被用来修改东西,但我保证我知道我在做什么."

希望这可以帮助!