【问题标题】:Copy constructor for C volatile bitfield structC volatile 位域结构的复制构造函数
【发布时间】:2017-12-31 04:34:12
【问题描述】:

美好的一天

我正在尝试在 C++11 项目中使用 C SD 驱动程序/文件系统库 (Keil MDK)。它是由 Keil MDK 5.23 中的包管理器添加的。我正在使用 ARMCC 5.06u4 进行编译

我收到警告 class "_ARM_MCI_STATUS" 没有合适的复制构造函数”,这很奇怪,因为它声明的标头有 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 的情况下编译,那么它编译没有问题。

有什么建议吗?

【问题讨论】:

  • 仅仅因为它被标记为extern "C" 并不意味着它绕过了C++规则。
  • 结构和类型名从不需要extern "C",只有函数需要。它的作用基本上是阻止name-mangling 的功能。
  • @RickAstley 我正在收集这一点,尽管我知道/不知道特定的 C++ 规则需要基本 C 位字段的复制构造函数。你知道吗?
  • 至于解决你的问题的方法,当你说你“手动将文件添加为C文件”时,你的意思是你给它起了一个带有.c后缀的名字吗?因为如果你想将它构建为 C 源文件,那就是你需要做的。
  • @Someprogrammerdude 该库是一个只有 .c/h 的 C 库。在 Keil 中,我将文件类型设置为“C 源代码”。尽管全局“--cpp”标志使所有文件都解释为 C++。这似乎是问题所在。

标签: c++ keil armcc


【解决方案1】:

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

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

这在cppreference explanation中有解释:

否则,隐式声明的复制构造函数是 T::T(T&)。 (注意 由于这些规则,隐式声明的复制构造函数 不能绑定到易失的左值参数。

而且在实际标准中(只是很难找到正确的子句,但它就在那里)。

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

      【解决方案3】:

      为了在 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++ 的知识。

      【讨论】:

        猜你喜欢
        • 2013-10-16
        • 1970-01-01
        • 1970-01-01
        • 2013-12-19
        • 1970-01-01
        • 2020-05-14
        • 2015-02-07
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多