C volatile 位域结构的复制构造函数

Copy constructor for C volatile bitfield struct

美好的一天

我正在尝试在 C++11 项目中使用 C SD driver/file 系统库 (Keil MDK)。它是由 Pack 管理器在 Keil MDK 5.23 中添加的。我正在使用 ARMCC 5.06u4

进行编译

我收到警告 class "_ARM_MCI_STATUS" 没有合适的复制构造函数”,这很奇怪,因为它声明的 header 有 extern "C" {

默认情况下,该包没有将其设置为 C 或 C++ 的选项,但我已将文件手动添加为 C 文件。还是有问题。

该结构在 extern "C" { 内声明为:

typedef volatile struct _ARM_MCI_STATUS {
    uint32_t command_active   : 1;        ///< Command active flag
    uint32_t command_timeout  : 1;        ///< Command timeout flag (cleared on start of next command)
    uint32_t command_error    : 1;        ///< Command error flag (cleared on start of next command)
    uint32_t transfer_active  : 1;        ///< Transfer active flag
    uint32_t transfer_timeout : 1;        ///< Transfer timeout flag (cleared on start of next command)
    uint32_t transfer_error   : 1;        ///< Transfer error flag (cleared on start of next command)
    uint32_t sdio_interrupt   : 1;        ///< SD I/O Interrupt flag (cleared on start of monitoring)
    uint32_t ccs              : 1;        ///< CCS flag (cleared on start of next command)
    uint32_t reserved         : 24;
} ARM_MCI_STATUS;

在以下位置返回结构时出现问题:

static ARM_MCI_STATUS GetStatus (MCI_RESOURCES *mci) {
  return mci->info->status;
}

其中 status 声明为 ARM_MCI_STATUS status;。我不明白为什么这应该是个问题。

如果我在没有 --cpp 的情况下进行编译,那么它可以正常编译。

有什么建议吗?

在 C++ 中,默认的复制构造函数用于常量引用。 但是,您正在传递一个 const volatile 引用;并且默认情况下没有复制构造函数。

您可能会发现将结构的每个成员标记为易失性比整个结构更好。

仅仅因为您的 struct 被标记为 extern "C" 并不意味着它不会仍然被编译为 C++ 代码。

这意味着return mci->info->status;调用隐式生成的复制构造函数。 因为 _ARM_MCI_STATUS 被标记为 volatile,它的成员是,这意味着采用 T& 的默认复制构造函数无法绑定到它传递的易失性左值引用。

这在cppreference explanation中有解释:

Otherwise, the implicitly-declared copy constructor is T::T(T&). (Note that due to these rules, the implicitly-declared copy constructor cannot bind to a volatile lvalue argument.)

并且在实际标准中(只是很难找到正确的条款,但它在那里)。

为了解决 Keil µVision 5.23 中的这个问题,我删除了全局“--cpp”标志。然后我确保所有 C++ 文件都在项目中它们自己的源代码组中。在该组的选项中,在 "C/C++" 选项卡下的 "Misc Controls" 字段中添加了“--cpp”标志。

在项目视图中右键单击文件夹可获得选项。

目前编译没有错误。问题似乎是,如果全局设置了 --cpp 标志,µVision 5.23 会将所有文件(c 或 cpp)编译为 C++。与 Eclipse 不同,似乎没有办法为 cpp 和 c 文件设置不同的标志。

感谢 UKMonkey 和 Rick Astley。学习了一些关于 volatile 和 C++ 的知识。