Delphi 7:int64大小的bug?

时间:2012-05-10 22:18:03

标签: delphi delphi-7

我编写了一个小函数来将MB转换为Bytes,但是,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;

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

4 个答案:

答案 0 :(得分: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.

<强>输出

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 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.

<强>输出

70359449600
70359449600

为了进行更全面的讨论,我建议您Barry Kelly's answer to another question

答案 1 :(得分:2)

我没碰巧在这个系统上安装D7,但我确实有Delphi 2007,其中,这段代码:

var
  FreeSpaceConverted, FreeSpace:int64;
begin
  try
     FreeSpace := 67100;
     FreeSpaceConverted := FreeSpace shl 20;
     writeln(FreeSpaceConverted);
     readln;
  except
    on E:Exception do
      Writeln(E.Classname, ': ', E.Message);
  end;
end.

收益率“70359449600”。

答案 2 :(得分:0)

我正在使用Delphi XE7。我认为问题在于将32位整数转换为64位整数。如果我使用你的代码,我会做同样的事情。但是,如果我首先将FreeSpace强制转换为int64,即

Const FreeSpace:int64 = 67100;

我得到了正确的结果。

答案 3 :(得分:-1)

好的,所以这条线不起作用 - &GT; FreeSpaceConverted:= FreeSpace shl 20;

也许你应该看这部分 - &GT; FreeSpace shl 20;

是的,FreeSpace shl 20,你可能想看看这个 - &GT;常量 - &GT; FreeSpace = 67100;

也许D7认为FreeSpace为Integer 32常量? 如果是这样,您可能希望将代码更改为此类代码 - &GT;常量 - &GT; FreeSpace:Int64 = 67100;

这里不需要无类型常量,除非你想做这样的事情 VAR    答:整数的数组[0..FreeSpace] 除此之外,你不需要无类型的常量。

更多信息 在Pascal中,无类型常量就像文本编辑器的替代品。您可以在使用数字的地方使用无类型常量。 它不需要任何内存引用,它只是一个文本编辑器替换。你无法进​​行任何操作 例: 常量   答:整数= 10;   B = 20;

开始   公司(A); // 有用   公司(B); //不仅它不起作用,还会产生编译错误 端;

比较              无类型常量类型常量 C #define A 20 long a = 20;
Pascal const A = 20; const A:整数= 20;
装配A等于20 A dd 20;双字,整数32                                                     ;装配中的等价物

相关问题