我想我有一个棘手的问题,但我相信你能帮助我 . 假设我有这样的函数:
char my_function (int example);
我在多种情况下使用此函数,有时它接收的参数是volatile变量,有时是非易失性变量 . 当我编译可以通过使用强制转换轻松删除的代码时,这会引起一些警告,但我想了解哪个是更安全的场景以及为什么 .
场景1:
原型: char my_function (int example);
int a;
volatile int b;
my_function (a); // Everything is fine.
my_function ((int)b); // Avoided the warning, by casting the variable and saying it's no longer volatile.
场景2:
原型: char my_function (volatile int example);
int a;
volatile int b;
my_function(b); // Everything is fine.
my_function((volatile int)a); // Avoided the warning, by casting 'a' saying that now it's volatile.
我理解volatile修饰符是如何工作的,我主要使用它,因为我编写了微控制器,我需要确保我的一些变量在硬件修改时永远不会被优化掉 . 我对于生成volatile修饰符有点困惑,这就是为什么我想要了解除了删除警告之外哪个更安全的情况 .
2 回答
这真的取决于
my_function
does 与其论点 .请记住,
volatile
会阻止某些优化 - 主要是它会强制每次引用变量时重新读取它 . 因此这段代码将为每个语句读取
a
,并且由于a
可能已更改它们之间的值,因此请给出正确的结果 .将
volatile
作为参数传递给函数时,只能获得一个变量的read
. 然后可以在函数内多次使用它(实际上失去了volatile
性质) .请记住,C是按值传递 . 当您调用该函数时
编译器生成代码以在调用代码中读取
b
一次,并将其读取的值推送到堆栈(通常),然后调用my_function
. 然后在my_function
中将此副本引用为example
,无论您多久引用example
,您将始终获得相同的值(即使原始的b
变量已经多次更改) .这可能正是您想要的 - 获取变量的快照并对其值进行多次计算 .
如果它不是您想要的,您需要考虑使用相应的
volatile
资格传递 pointer .并称之为:
然后在
my_function
内引用*example
.演员实际上没有做任何事情 . 在调用my_function(b)中;代码读取volatile int b . 在阅读期间,这就是“易变”的重要因素 . 读取的结果已经是int而不是volatile int . 没有volatile int值 . 即使存在volatile int值,将其传递给my_function也会将其转换为plain int,就像强制转换一样 .
可能是编译器假定将volatile变量传递给函数是危险的值得警告,并且通过向int添加强制转换,表明您知道自己在做什么 .