[英]volatile struct vs. typecast
I have the following declarations in my code: 我的代码中包含以下声明:
h file: h文件:
typedef struct {
bool qualified : 1;
bool running : 1;
} calibration_state_t;
calibration_state_t get_calibration_state();
cpp file: cpp文件:
volatile calibration_state_t calibration_state = {false ,false};
The function 功能
calibration_state_t get_calibration_state() {
return *(calibration_state_t *)&calibration_state;
}
compiles. 编译。 However if I replace the return statement with
但是,如果我将return语句替换为
return (calibration_state_t)calibration_state;
It fails with 它失败了
dcf77.cpp: In function ‘DCF77_Frequency_Control::calibration_state_t DCF77_Frequency_Control::get_calibration_state()’:
dcf77.cpp:2923:37: error: no matching function for call to ‘DCF77_Frequency_Control::calibration_state_t::calibration_state_t(volatile DCF77_Frequency_Control::calibration_state_t&)’
dcf77.h:204:7: note: candidates are: DCF77_Frequency_Control::calibration_state_t::calibration_state_t()
dcf77.h:204:7: note: DCF77_Frequency_Control::calibration_state_t::calibration_state_t(const DCF77_Frequency_Control::calibration_state_t&)
The compiler is avr-gcc but I suspect this does not matter. 编译器是avr-gcc,但我怀疑这没有关系。 Why does the compiler fail to compile the type cast?
为何编译器无法编译类型转换? How would I get to the desired return value in a clean way?
我如何以一种干净的方式达到期望的返回值?
Your code that uses a cast has undefined behavior (§7.1.6.1 [dcl.type.cv]/p6): 您使用强制类型转换的代码具有未定义的行为(§7.1.6.1[dcl.type.cv] / p6):
If an attempt is made to refer to an object defined with a volatile-qualified type through the use of a glvalue with a non-volatile-qualified type, the program behavior is undefined.
如果试图通过使用具有非挥发限定类型的glvalue来引用以挥发限定类型定义的对象,则程序行为是不确定的。
*(calibration_state_t *)&calibration_state
is a glvalue of type calibration_state_t
, a non-volatile-qualified type, and is being used to refer to calibration_state
, an object defined with a volatile-qualified type. *(calibration_state_t *)&calibration_state
是非定性类型的calibration_state_t
类型的glvalue,用于引用calibration_state
,该对象是用非定性类型定义的对象。 Undefined behavior results. 未定义的行为结果。
Relying on undefined behavior to get the semantics you want is incredibly dangerous. 依靠未定义的行为来获取所需的语义是非常危险的。 While the compiler is unlikely to actually conjure nasal demons or blow your legs off (though it is allowed to), an optimizing compiler may legally assume from the undefined behavior that
get_calibration_state
will never be called, and that any code path containing it is unreachable, and generate code accordingly. 尽管编译器不太可能实际产生鼻恶魔或
get_calibration_state
(尽管允许这样做),但优化的编译器可能会根据未定义的行为合法地假定永远不会调用get_calibration_state
,并且包含该代码的任何代码路径均无法访问,并据此生成代码。 This kind of optimizations depending on undefined behavior can and do happen. 这种根据未定义行为的优化可以并且确实会发生。
In reference binding, volatile
is like const
- you can't bind a const
object to a non- const
reference, and you can't bind a volatile
object to a non- volatile
reference. 在引用绑定中,
volatile
就像const
一样-您不能将const
对象绑定到非const
引用,也不能将volatile
对象绑定到非易失volatile
引用。 Give your class a copy constructor that takes a const volatile &
. 给您的类一个采用
const volatile &
的复制构造const volatile &
。
What is the desired behavior exactly? 期望的行为到底是什么? Must ordering be preserved, for example?
例如,必须保留订购吗? If something else sets
qualified
and then running
, is it okay to get the old value of qualified
but the new value of running
? 如果还有其他条件设置
qualified
然后running
,是否可以获取qualified
的旧值但获得新的running
值?
Because the structure is volatile, operations on it are part of the visible behavior of the program. 由于结构是易失性的,因此对其进行的操作是程序可见行为的一部分。 That is, this:
也就是说,这是:
calibration_state_t get_calibration_state()
{
calibration_state_t ret;
ret.qualified = calibration_state.qualified;
ret.running = calibration_state.running;
return ret;
}
Is not the same as: 与以下内容不同:
calibration_state_t get_calibration_state()
{
calibration_state_t ret;
ret.running = calibration_state.running;
ret.qualified = calibration_state.qualified;
return ret;
}
So, you have to code what you want. 因此,您必须编写所需的代码。 How can the compiler know what behavior you want?
编译器如何知道您想要什么行为? You got some behavior by lying to the compiler, but I doubt it's the behavior you want.
您对编译器撒谎有一些行为,但是我怀疑这是您想要的行为。
For me it looks that: 对我来说,看起来:
return *(calibration_state_t *)&calibration_state;
explicitly removes the volatile
specifier, so the implicitly defined copy constructor: 显式删除
volatile
说明符,因此隐式定义的副本构造函数:
calibration_state_t(const calibration_state_t&)
is executed. 被执行。
When you don't cast the calibration_state
instance first, then compiler can not call the copy constructor ( volatile
remains). 当您不首先强制转换
calibration_state
实例时,编译器将无法调用复制构造函数( volatile
仍然存在)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.