Delphi警告W1073组合有符号类型和无符号64位类型-视为无符号类型

时间:2019-01-15 23:26:52

标签: delphi types warnings

我在以下代码行中收到主题警告;

SelectedFilesSize := SelectedFilesSize +
  UInt64(IdList.GetPropertyValue(TShellColumns.Size)) *
  ifthen(Selected, 1, -1);

具体地说,IDE突出显示了第三行。

SelectedFilesSize被声明为UInt64。

代码在我运行时似乎可以正常工作;如果我选择一个项目,则其文件大小会加到总数中;如果我取消选择一个文件,则会减去其大小。

我知道我可以使用{$ WARN COMBINING_SIGNED_UNSIGNED64 OFF}取消此警告。

有人可以解释吗?如果SelectedFilesSize变大,会不会产生不可预见的影响?还是对特定目标平台有影响?

Delphi 10.3,Win32和Win64目标

1 个答案:

答案 0 :(得分:3)

这将在这里起作用,但警告是正确的。

如果将 UInt64 乘以-1,则实际上是将其乘以$FFFFFFFFFFFFFFFF。最终结果将是一个128位的值,但低64位将与有符号乘法相同(这也是代码生成器经常生成imul操作码的原因,甚至对于无符号乘法:低位将是正确的,只是-未使用-高位将是不正确的)。高64位将不会被使用,所以没关系。

如果将该值(实际上为负)添加到另一个 UInt64 中(例如 SelectedFilesSize ),则64位的结果将再次正确。加法时,CPU不会区分正值或负值。产生的CPU 标志(进位,溢出)将指示溢出,但是如果您不使用范围或溢出检查而忽略了它,那么您的代码就可以了。

但是,如果启用了范围检查或溢出检查,您的代码可能会产生运行时错误。

换句话说,之所以可行,是因为任何多余的高位(第64位及以上)都可以忽略。否则,值将是错误的。参见示例。

示例

假设您的IdList.GetPropertyValue(TShellColumns.Size)是420。然后您将执行:

$00000000000001A4 * $FFFFFFFFFFFFFFFF = $00000000000001A3FFFFFFFFFFFFFF5C

这是一个很大的但正值,但是幸运的是,低64位($FFFFFFFFFFFFFF5C)可以解释为-420(128位的负值实际上是$FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5C-420)。

现在说您的SelectedFileSize100000(或十六进制$00000000000186A0)。然后您得到:

$00000000000186A0 + $FFFFFFFFFFFFFF5C = $00000000000184FC 
(or actually $100000000000184FC, but the top bit -- the carry -- is ignored).

$00000000000184FC是十进制的99580,因此正是您想要的值。