1

在 Visual C++ 2019 上:

以下代码呈现警告:

warning C4267: 'argument': conversion from 'size_t' to 'DWORD', possible loss of data

HANDLE events[2];
WaitForMultipleObjects(std::size(events), events, FALSE, INFINITE);

但是使用_countof(events)不会给出任何警告。请注意,std::size调用的是模板重载函数。这个:

template<class _Ty,
    size_t _Size> inline
    constexpr size_t size(const _Ty(&)[_Size]) _NOEXCEPT
    {   // get dimension for array
    return (_Size);
    }

本质上返回 a size_t,而函数是constexpr. 这就是数组声明有效的原因:

HANDLE Events[2];
int arr[std::size(Events)];

但以下代码不会在没有警告的情况下编译:

DWORD sz1 = std::size(Events);

这没关系:

DWORD sz2= _countof(Events);

有什么具体原因,还是编译器错误?

相关: sizeof 运算符的返回类型是什么?

编辑,有趣的是,这些也可以正常工作:

HANDLE events[2];
constexpr size_t s1 = sizeof(Events) / sizeof(Events[0]);
constexpr size_t s2 = std::size(Events);

变量s1s2被视为真正的编译时值,而不是std::size()结果本身!

4

2 回答 2

0

如果您阅读警告消息,这是关于从类型size_t(的结果std::size(Events)转换为 DWORD(的类型)的抱怨sz1

问题是在 64 位系统size_t上通常是 64 位无符号整数类型。但是 Windows 定义DWORD32位无符号整数类型。

使用_countof不会产生警告可能是因为 MSVC 编译器的特定于实现的行为。

于 2020-03-03T07:22:25.783 回答
0

DWORD在 Windows 上始终是 32 位无符号的。

size_t通常是带有 64 位编译器的 64 位 unsigned long long。将您的构建切换到 32 位,它是一个 32 位无符号整数。

将 64 位 int 分配给 32 位 - 是的,这是一个警告条件。

奇怪的是:

WaitForMultipleObjects(sizeof(events) / sizeof(events[0]), events, FALSE, INFINITE);

编译没有问题。我猜这是因为编译器可以推断该const表达式的类型减少到 unsigned int 或更小。

但是这个:

auto count = sizeof(events) / sizeof(events[0]);
WaitForMultipleObjects(count, events, FALSE, INFINITE);

生成几乎相同的警告,因为count计算结果为 64 位 unsigned long long。

但这也将在没有警告的情况下编译:

const auto count = sizeof(events) / sizeof(events[0]);
WaitForMultipleObjects(count, events, FALSE, INFINITE);
于 2020-03-03T07:25:00.280 回答