Целочисленное переполнение в операциях

Следующий код:

UINT32 dword = 4294967295;

if(dword + 1 != 0) // condition

В таких операциях есть ли гарантия, что всегда используется самый большой (целый) регистр (доступный по архитектуре)? и выше условие всегда будет истинным в 64-битном режиме, а ложным для 32-битного режима?

1

Решение

Это будет зависеть от того, какого типа UINT32 на самом деле.

Если это тип без знака (как и следовало ожидать), то результаты гарантированно будут уменьшены по модулю наибольшего значения, которое может быть представлено + 1, поэтому код такой:

if (std::numeric_limits<T>::is_unsigned)
assert(std::numeric_limits<T>::max()+1==0);

…должен преуспеть. OTOH, основываясь на названии, мы обычно ожидаем, что это будет 32-битный тип независимо от реализации, размера регистра и т. Д., Поэтому мы ожидаем получить тот же результат независимо от этого.

Редактировать: [извините, пришлось остановиться и покормить ребенка на несколько минут] Я должен добавить более подробно. Хотя мы, безусловно, можем надеяться, что на практике это маловероятно, вполне возможно, что UINT32 действительно может быть (скажем) 16-битным unsigned short, Для обсуждения давайте предположим, что int 32 бита.

В этом случае, dword+1 будет включать в себя математику между unsigned short и int (неявный тип 1). В таком случае, dword будет на самом деле инициализирован до 65535. Затем, когда вы сделали сложение, что 65535 будет повышен до 32-разрядного int, а также 1 добавлено как intТаким образом, результат будет 65536.

По крайней мере, теоретически, то же самое могло бы произойти, если бы UINT32 был 32-разрядным типом без знака (как мы и ожидали), но int был 64-битный тип. Снова, dword будет повышен до int перед выполнением математических вычислений математика будет выполняться не на 32-разрядных, а на 64-разрядных величинах, поэтому (опять же) результат не будет обнуляться до 0.

3

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]