Sal*_*dor 6 delphi 64-bit delphi-xe2
我正在将Delphi项目移植到64位,并且我遇到了一行代码,其中包含IN运算符.
编译器引发此错误
E2010不兼容类型:'整数'和'Int64'
我写了这个示例应用程序来复制问题.
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils;
Var
I : Integer;
L : Array of string;
begin
try
if I in [0, High(L)] then
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
readln;
end.
Run Code Online (Sandbox Code Playgroud)
这段代码工作正常32位,但为什么不用Delphi XE2 64位编译?我该如何解决这个问题?
*更新*
似乎我的帖子引起了很多混淆(对不起),只是为了解释我移植的原始代码更复杂,我只是将这段代码作为样本来说明问题.原始代码使用in运算符来检查一个值(小于255)是否属于一组值(所有次要或等于255),如此
i in [0,1,3,50,60,70,80,127,High(LArray)]
Run Code Online (Sandbox Code Playgroud)
此代码无法编译,因为High函数返回的是8字节值,这不是序数值.并且In运算符只能在具有序数值的集合中使用.
仅供参考,High函数返回的结果大小因参数传递的参数而异.
检查此样本
Writeln(SizeOf(High(Byte)));
Writeln(SizeOf(High(Char)));
Writeln(SizeOf(High(Word)));
Writeln(SizeOf(High(Integer)));
Writeln(SizeOf(High(NativeInt)));
Writeln(SizeOf(High(TBytes)));
Run Code Online (Sandbox Code Playgroud)
最后,您可以修复代码,将High函数的结果转换为整数.
if I in [0, Integer(High(L))] then
Run Code Online (Sandbox Code Playgroud)
UPDATE
检查David提供的其他信息,并记住在使用in运算符检查变量值集合中的值的成员资格时要非常小心.所述in操作者仅检查每个元素(在Delphi 32位)的至少显著字节.
检查此样本
i:=257;
Writeln( 1 in [i]);
Run Code Online (Sandbox Code Playgroud)
返回true,因为257的低字节为1.
在Delphi 64位中,大于255的值被删除.所以这段代码
i:=257;
Writeln( 1 in [i]);
Run Code Online (Sandbox Code Playgroud)
将返回false,因为相当于
Writeln( 1 in []);
Run Code Online (Sandbox Code Playgroud)
RRUZ说的非常正确。
补充一点解释,在 64 位 Delphi 中,动态数组索引可以是 64 位宽。例如,在使用大 TBytes 内存块时,这显然是必需的。因此该high函数必须返回一个足够宽的类型值以容纳所有可能的索引。因此,high当应用于动态数组时,返回类型为 的值Int64。
一旦您开始编译 64 位代码,该in运算符就不再适合您要解决的问题。虽然您可以使用 RRUZ 建议的转换,但编写这样的代码可能会更清晰
if (I=low(L)) or (I=high(L)) then
Run Code Online (Sandbox Code Playgroud)
虽然该in运算符可以生成非常可读的代码,但我认为Integer这里的强制转换是不可接受的。当您第一次拥有一个包含多个high(Integer)元素的数组时,这只会为您设置一个陷阱。当这种情况发生时,带有强制转换的代码将停止工作。
但事实上问题远不止于此。in在到达元素之前,代码的版本就失败了high(Integer)。事实证明,您的代码虽然可以编译,但并不能真正工作。例如,考虑这个程序:
program WeirdSets;
{$APPTYPE CONSOLE}
uses
SysUtils;
var
a: array of Integer;
begin
SetLength(a, 257);
Writeln(BoolToStr(Length(a) in [0, Length(a)], True));
end.
Run Code Online (Sandbox Code Playgroud)
您期望该程序输出True,但实际上它输出False. 如果你要写
Writeln(BoolToStr(Length(a) in [0, 257], True));
Run Code Online (Sandbox Code Playgroud)
然后编译器报告:
[DCC Error] WeirdSets.dpr(9): E1012 Constant expression violates subrange bounds
Run Code Online (Sandbox Code Playgroud)
这里的根本问题是集合限制为 256 个元素,因此一旦数组的长度大于该长度,您的代码就会停止工作。
遗憾的是,Delphi 对集合的支持根本不够,迫切需要引起重视。
我也想知道你是否真的想写
if I in [0..High(L)] then
Run Code Online (Sandbox Code Playgroud)
如果是这样,那么我建议您使用InRange中的函数Math。
if InRange(I, 0, High(L)) then
Run Code Online (Sandbox Code Playgroud)
甚至更好
if InRange(I, low(L), High(L)) then
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
980 次 |
| 最近记录: |