在 c 中转换 volatile 变量
Casting volatile variable in c
我想我有一个棘手的问题,但我相信你能帮助我。
假设我有这样的功能:
char my_function (int example);
我在多种情况下使用这个函数,有时它接收的参数是一个volatile变量,有时是一个non-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 修饰符有点困惑,这就是为什么我想了解除了删除警告之外哪种情况更安全。
这实际上取决于 my_function
的参数。
请记住,volatile
会阻止某些优化 - 主要是它会在每次引用变量时强制重新读取它。因此这段代码
volatile int a;
int b;
// ...
b = a + 1;
b = a + 2;
将为每个语句读取 a
,并且由于 a
可能在它们之间更改了值,因此给出正确的结果。
当您将 volatile
作为参数传递给函数时,您只会得到一个 read
变量。然后可以在函数中多次使用它(实际上失去了 volatile
的性质)。
记住 C 是按值传递的。当您调用函数时
my_function((int)b); // b is declared volatile
编译器生成代码在调用代码中读取一次b
,并将读取的值压入堆栈(通常),然后调用my_function
。然后,此副本在 my_function
中被引用为 example
,无论您引用 example
的频率如何,您将始终获得相同的值(即使原始 b
变量自此改变了很多次)。
这可能正是您想要的 - 拍摄变量快照并对其值进行多次计算。
如果这不是您想要的,您需要考虑传入一个具有适当 volatile
限定条件的 指针。
char my_function( volatile int *example);
并这样称呼它:
my_function(&a);
my_function(&b);
然后在my_function
.
中引用*example
演员表实际上什么也没做。在调用my_function(b);代码读取 volatile int b。在阅读期间,这就是 "volatile" 重要的地方。读取的结果已经是一个 int 而不是 volatile int。没有 volatile int 值。即使存在 volatile int 值,将其传递给 my_function 也会将其转换为纯 int,就像强制转换一样。
可能编译器假设将 volatile int 变量传递给函数是危险的,值得警告,并且通过向 int 添加强制转换表明您知道你在做什么。
我想我有一个棘手的问题,但我相信你能帮助我。 假设我有这样的功能:
char my_function (int example);
我在多种情况下使用这个函数,有时它接收的参数是一个volatile变量,有时是一个non-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 修饰符有点困惑,这就是为什么我想了解除了删除警告之外哪种情况更安全。
这实际上取决于 my_function
的参数。
请记住,volatile
会阻止某些优化 - 主要是它会在每次引用变量时强制重新读取它。因此这段代码
volatile int a;
int b;
// ...
b = a + 1;
b = a + 2;
将为每个语句读取 a
,并且由于 a
可能在它们之间更改了值,因此给出正确的结果。
当您将 volatile
作为参数传递给函数时,您只会得到一个 read
变量。然后可以在函数中多次使用它(实际上失去了 volatile
的性质)。
记住 C 是按值传递的。当您调用函数时
my_function((int)b); // b is declared volatile
编译器生成代码在调用代码中读取一次b
,并将读取的值压入堆栈(通常),然后调用my_function
。然后,此副本在 my_function
中被引用为 example
,无论您引用 example
的频率如何,您将始终获得相同的值(即使原始 b
变量自此改变了很多次)。
这可能正是您想要的 - 拍摄变量快照并对其值进行多次计算。
如果这不是您想要的,您需要考虑传入一个具有适当 volatile
限定条件的 指针。
char my_function( volatile int *example);
并这样称呼它:
my_function(&a);
my_function(&b);
然后在my_function
.
*example
演员表实际上什么也没做。在调用my_function(b);代码读取 volatile int b。在阅读期间,这就是 "volatile" 重要的地方。读取的结果已经是一个 int 而不是 volatile int。没有 volatile int 值。即使存在 volatile int 值,将其传递给 my_function 也会将其转换为纯 int,就像强制转换一样。
可能编译器假设将 volatile int 变量传递给函数是危险的,值得警告,并且通过向 int 添加强制转换表明您知道你在做什么。