Почему результат std :: size не компилируется, ИЛИ не является size_t? - PullRequest
1 голос
/ 03 марта 2020

В 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);
    }

Что по сути равно , возвращая size_t, а функция - constexpr. И вот почему объявление массива работает:

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

Но следующий код не будет скомпилирован без предупреждения:

DWORD sz1 = std::size(Events);

Это нормально:

DWORD sz2= _countof(Events);

Любые параметры c причина или ошибка компилятора?

Соответствующий: Какой тип возврата у оператора sizeof?

EDIT , Интересно, что они также будут работать нормально:

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

Переменные s1 и s2 принимаются как истинные значения времени компиляции, но не сам результат std::size()!

Ответы [ 2 ]

0 голосов
/ 03 марта 2020

DWORD всегда 32-битный без знака на Windows.

size_t обычно является 64-битным длинным без знака с 64-битным компилятором. Переключите сборку на 32-битную, и это будет 32-битное целое число без знака.

Назначение 64-битного целого числа 32-битному - да, это условие предупреждения.

Что странно this:

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-битному длинному без знака.

Но это также скомпилируется без предупреждения:

const auto count = sizeof(events) / sizeof(events[0]);
WaitForMultipleObjects(count, events, FALSE, INFINITE);
0 голосов
/ 03 марта 2020

Если вы читаете предупреждающие сообщения, это жалоба на преобразование из типа size_t (результат std::size(Events)) в DWORD (тип sz1).

Проблема заключается в том, что в 64-разрядной системе size_t обычно представляет собой 64-разрядное целое число без знака. Но Windows определяют DWORD как 32 битовый целочисленный тип без знака.

То, что использование _countof не генерирует предупреждение, может быть связано с тем, что специфического для реализации c поведения компилятора MSV C.

...