volatile结构与类型转换

时间:2014-09-02 19:14:00

标签: c++ gcc struct volatile

我的代码中有以下声明:

h file:

typedef struct {
    bool qualified : 1;
    bool running : 1;
} calibration_state_t;

calibration_state_t get_calibration_state();

cpp文件:

volatile calibration_state_t calibration_state = {false ,false};

功能

calibration_state_t get_calibration_state() {
    return *(calibration_state_t *)&calibration_state;
}

编译。但是,如果我用

替换return语句
return (calibration_state_t)calibration_state;

失败了

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&)

编译器是avr-gcc,但我怀疑这没关系。为什么编译器无法编译类型转换?如何以干净的方式获得所需的返回值?

3 个答案:

答案 0 :(得分:3)

使用强制转换的代码具有未定义的行为(第7.1.6.1节[dcl.type.cv] / p6):

  

如果尝试引用用a定义的对象   通过使用带glvalue的volatile限定类型   非易失性限定类型,程序行为未定义。

*(calibration_state_t *)&calibration_state是类型为calibration_state_t的glvalue,是一种非易失性限定类型,用于引用calibration_state,这是一个使用volatile限定类型定义的对象。未定义的行为结果。

依靠未定义的行为来获取您想要的语义是非常危险的。虽然编译器实际上不可能实现鼻子恶魔或者断掉你的腿(虽然它被允许),但是优化编译器可以从未定义的行为中合法地假设get_calibration_state永远不会被调用,并且包含任何代码路径它无法访问,并相应地生成代码。这种取决于未定义行为的优化可能并且确实会发生。

在引用绑定中,volatileconst类似 - 您无法将const对象绑定到非const引用,并且您无法绑定volatile反对非volatile引用。为您的班级提供一个带有const volatile &

的复制构造函数

答案 1 :(得分:2)

究竟是什么样的行为?例如,必须保留订购吗?如果其他内容设置为qualified然后设置running,是否可以获得qualified的旧值但是running的新值?

因为结构是易失性的,所以对它的操作是程序可见行为的一部分。就是这样:

calibration_state_t get_calibration_state()
{
    calibration_state_t ret;
    ret.qualified = calibration_state.qualified;
    ret.running = calibration_state.running;
    return ret;
}

不一样:

calibration_state_t get_calibration_state()
{
    calibration_state_t ret;
    ret.running = calibration_state.running;
    ret.qualified = calibration_state.qualified;
    return ret;
}

所以,你必须编写你想要的代码。编译器如何知道您想要的行为?通过向编译器说谎,你得到了一些行为,但我怀疑它是你想要的行为。

答案 2 :(得分:1)

对我而言,看起来:

return *(calibration_state_t *)&calibration_state;

显式删除volatile说明符,因此隐式定义的复制构造函数:

calibration_state_t(const calibration_state_t&)

已执行。

如果您没有先放置calibration_state实例,那么编译器就无法调用复制构造函数(volatile仍然存在)。

相关问题