c++ - 根据 MSVC,具有 volatile 成员的结构不再是 POD

标签 c++ c visual-c++ volatile

#include <cstdint>
#include <type_traits>

extern "C"
{
    struct thread_shared_struct
    {
        volatile uint32_t ccr;
    };

    struct thread_shared_struct getStuff();
}

static_assert(std::is_pod<thread_shared_struct>::value, "thread_shared_struct isn't a POD");

int main(int argc, char** argv)
{
    thread_shared_struct m = getStuff();
    return 0;
}

参见this code on godbolt

当然,这个示例没有多大意义,但它是从更大的代码库中最小化我的问题的再现。

使用 GCC(主干)和 Clang(主干),效果很好。

使用 MSVC(x64、19.22),static_assert 失败并且 getStuff() 生成错误,因为它尝试返回与 C 调用约定不兼容的类型。

如果删除“ volatile ”,则一切正常。

MSVC 认为 thread_shared_struct 不是 POD 类型是错误的吗?

extern“C”部分位于 C header 中,需要保持原样。我如何在 C++ 中使用它?

最佳答案

来自the Microsoft documentation :

When a class or struct is both trivial and standard-layout, it is a POD (Plain Old Data) type.

稍后描述文字类型,包括以下条件:

Additionally, all its non-static data members and base classes must be literal types and not volatile.

页面上的其他任何地方都没有提到“ volatile ”。

这一切都符合我们发现的in the standard .

因此,我断定这是一个编译器错误。


getStuff() generates an error because it attempts to return a type that is not compatible with the C calling convention.

实际上,这只是一个警告 (C4190),如果您愿意,您可以将其禁用。 x86_64 上的 Visual Studio 只有一种调用约定(描述为 here )。您的代码仍然可以正常工作。 VS 只是警告您,如果您实际尝试在 C 中使用该类型,该类型将无法工作。 extern "C" 并不意味着编译为 C。

但是,收到此警告确实表明该错误确实存在于编译器中,而不仅仅是存在于 std::is_pod 的实现中。


此外,我建议在新代码中避免使用 POD 术语和 std::is_pod 特征,因为它们是 deprecated from C++20 .


The extern "C" part is in a C header that needs to stay as is. How could I use it from C++?

任何实际上不需要类型符合 VS 的“POD”定义的东西,尽管有类型特征,应该没问题。

关于c++ - 根据 MSVC,具有 volatile 成员的结构不再是 POD,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59103157/

相关文章:

c++ - 如何访问另一个本地的本地变量?

c++ - 如何在基于 MFC 对话框的应用程序中为复选框捕获 MouseMove 事件?

c - 在 Linux 中设置 FD 标志

visual-c++ - __in,__out,__in_opt的含义

c++ - 在Qt中,如何使用定时器来启用/禁用一个功能?

c++ - C 和 C++ 中的函数 clrscr

c++ - 在 C++ 中将 long long 转换为十六进制和二进制

c++ - std::vector 转换为 cl_float

c++ - 信号执行期间的 sigprocmask

c++ - 使用来自另一个 C++ 类的全局变量创建 C++ 源文件的多个实例