德尔福 7 : int64 size bug?

标签 delphi delphi-7

我写了一个小函数来将 MB 转换为字节,但是 int64 中似乎有一个错误。根据文档,int64 的范围从 -9223372036854775808 到 9223372036854775807,但我的结果不同......很多:

Const FreeSpace = 67100;

var FreeSpaceConverted :int64;
.
.
.

FreeSpaceConverted := FreeSpace shl 20;

对 FreeSpace 使用 67100 的值会得到 1639972864 而不是 70359449600 的值。很明显,转换用完了空间并回绕。 int64 的实际大小似乎是 70359449600 - 1639972864 = 68719476736 = 2^36 而它应该是 2^63-1。 36 的指数看起来很奇怪。这可能是编译器本身的数字扭曲吗?

此外,使用以下替代方法会给出错误“转换或算术运算溢出”,即使它不应该:
FreeSpaceConverted := FreeSpace * 1024 * 1024;

另一方面,以下替代方法确实有效:
FreeSpaceConverted := FreeSpace * 1024;
FreeSpaceConverted := FreeSpaceConverted * 1024;

这是正常行为吗?如果是这样,这一切的原因是什么?

最佳答案

您在问题中包含的所有代码在 Delphi 7 中都可以正常工作。

program Int64Test;

{$APPTYPE CONSOLE}

var
  FreeSpaceConverted, FreeSpace: Int64;

begin
  FreeSpace := 67100;
  FreeSpaceConverted := FreeSpace shl 20;
  Writeln(FreeSpaceConverted);
  FreeSpaceConverted := FreeSpace * 1024 * 1024;
  Writeln(FreeSpaceConverted);
  Readln;
end.

输出
70359449600
70359449600

您的实际代码与您在问题中所述的不同。事实上,FreeSpace在您的代码中被声明为 32 位类型,可能是 Integer .例如,我不得不在这里猜测一下:
program Int64Test;

{$APPTYPE CONSOLE}

var
  FreeSpace: Integer;
  FreeSpaceConverted: Int64;

begin
  FreeSpace := 67100;
  FreeSpaceConverted := FreeSpace shl 20;
  Writeln(FreeSpaceConverted);
  FreeSpaceConverted := FreeSpace * 1024 * 1024;
  Writeln(FreeSpaceConverted);
  Readln;
end.

输出
1639972864
1639972864

如果我们启用溢出检查,那么乘法代码会导致溢出异常,正如您报告的那样。

现在考虑 FreeSpace shl 20FreeSpace是一个整数。编译器将此解释为 32 位整数运算,并将更高有效位移出 32 位寄存器的末尾。您分配给 64 位整数的事实无关紧要。重要的是表达式中的数据类型。您可以通过对 Int64 进行强制转换来使代码按照您想要的方式运行。在右手侧。
program Int64Test;

{$APPTYPE CONSOLE}

var
  FreeSpace: Integer;
  FreeSpaceConverted: Int64;

begin
  FreeSpace := 67100;
  FreeSpaceConverted := Int64(FreeSpace) shl 20;
  Writeln(FreeSpaceConverted);
  FreeSpaceConverted := Int64(FreeSpace) * 1024 * 1024;
  Writeln(FreeSpaceConverted);
  Readln;
end.

输出
70359449600
70359449600

如需更全面的讨论,请参阅 Barry Kelly's answer to another question .

关于德尔福 7 : int64 size bug?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10542957/

相关文章:

德尔福64位: finding incorrect casts?

delphi - 范围检查错误的原因(Delphi)

delphi - 更改exe中的浮点值

delphi - 编写 Total Commander .WCX(加壳器)插件

Delphi 7,如何将Paintbox内容复制到Tbitmap?

forms - 禁用表单上升到顶部

delphi - 在 Delphi 2010 或更高版本中获取文件的大小?

delphi - 检查变体值 "Nothing"

delphi - 如何将单元中定义的组件添加到Delphi调色板?

delphi - 如何从表单中删除标题栏