Это будет работать здесь, но предупреждение верно.
Если вы умножаете UInt64 на -1
, вы фактически умножаете его на $FFFFFFFFFFFFFFFF
. Конечным результатом будет 128-битное значение, , но младшие 64 бита будут такими же, как и для умножения со знаком (именно поэтому генератор кода часто выдает код операции imul
, даже для умножения с несимметричным умножением. : младшие биты будут правильными, только & mdash; unused & mdash; старшие биты не будут). Старшие 64 бита все равно не будут использоваться, поэтому они не имеют значения.
Если вы добавите это (фактически отрицательное) значение к другому UInt64 (например, SelectedFilesSize ), 64-битный результат снова будет правильным. Процессор не различает положительные или отрицательные значения при добавлении. Результирующие CPU flags (перенос, переполнение) будут указывать на переполнение, но если вы проигнорируете это, не используя проверки диапазона или переполнения, ваш код будет в порядке.
Ваш код, скорее всего, выдаст ошибку времени выполнения, если включены проверки диапазона или переполнения.
Другими словами, это работает, потому что любой лишний старший бит & mdash; 64-й бит и выше - & mdash; можно игнорировать . В противном случае значения будут неправильными. Смотрите пример.
Пример * +1031 ** * одна тысяча тридцать две
Скажите, что IdList.GetPropertyValue(TShellColumns.Size)
составляет 420. Затем вы выполняете:
$00000000000001A4 * $FFFFFFFFFFFFFFFF = $00000000000001A3FFFFFFFFFFFFFF5C
Это огромное , но положительное число, но, к счастью, младшие 64 бита ($FFFFFFFFFFFFFF5C
) можно интерпретировать как -420
(действительно отрицательное значение в 128 битах будет $FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5C
или -420
).
Теперь скажите, что ваш SelectedFileSize
равен 100000
(или гекс $00000000000186A0
). Тогда вы получите:
$00000000000186A0 + $FFFFFFFFFFFFFF5C = $00000000000184FC
(or actually $100000000000184FC, but the top bit -- the carry -- is ignored).
$00000000000184FC
- это 99580
в десятичном виде, поэтому именно то значение, которое вы хотели.