Delphi 7:int64大小的bug?

Zer*_*y99 1 delphi delphi-7

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

Const FreeSpace = 67100;

var FreeSpaceConverted :int64;
.
.
.

FreeSpaceConverted := FreeSpace shl 20;
Run Code Online (Sandbox Code Playgroud)

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

此外,使用以下替代方法会出现错误"转换或算术运算中的溢出",即使它不应该:

FreeSpaceConverted := FreeSpace * 1024 * 1024;
Run Code Online (Sandbox Code Playgroud)

另一方面,以下替代方案确实有效:

FreeSpaceConverted := FreeSpace * 1024;
FreeSpaceConverted := FreeSpaceConverted * 1024;
Run Code Online (Sandbox Code Playgroud)

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

Dav*_*nan 12

您在问题中包含的所有代码在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.
Run Code Online (Sandbox Code Playgroud)

产量

70359449600
70359449600
Run Code Online (Sandbox Code Playgroud)

您的实际代码与您在问题中所述的不同.实际上,可能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.
Run Code Online (Sandbox Code Playgroud)

产量

1639972864
1639972864
Run Code Online (Sandbox Code Playgroud)

如果我们启用溢出检查,则在您报告时,乘法代码会导致溢出异常.


现在考虑FreeSpace shl 20何时FreeSpace是整数.编译器将其解释为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.
Run Code Online (Sandbox Code Playgroud)

产量

70359449600
70359449600
Run Code Online (Sandbox Code Playgroud)

为了更全面的讨论,我向您推荐Barry Kelly对另一个问题的回答.