Следующий код:
UINT32 dword = 4294967295;
if(dword + 1 != 0) // condition
В таких операциях есть ли гарантия, что всегда используется самый большой (целый) регистр (доступный по архитектуре)? и выше условие всегда будет истинным в 64-битном режиме, а ложным для 32-битного режима?
Это будет зависеть от того, какого типа 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.
Других решений пока нет …