Delphi 从基数到单数的类型转换

Delphi 从基数到单数的类型转换,delphi,delphi-10.1-berlin,Delphi,Delphi 10.1 Berlin,Cardinal和Single都是4字节/32位的数据类型,但当我将它们相互键入时,在(柏林)中会出现无效的键入错误 我不是说在这两种类型之间进行转换,因为这只会存储基数数据的23位(数据的分数部分)。我需要将至少30位数据存储到一个变量中。我有很好的理由(类型不能更改),我将很高兴详细说明 如何键入单个变量?您可以使用变量记录访问相同的底层内存: type TConverter = record case integer of 0 : (c: cardinal); 1

Cardinal
Single
都是4字节/32位的数据类型,但当我将它们相互键入时,在(柏林)中会出现
无效的键入错误

我不是说在这两种类型之间进行转换,因为这只会存储基数数据的23位(数据的分数部分)。我需要将至少30位数据存储到一个
变量中。我有很好的理由(类型不能更改),我将很高兴详细说明


如何键入单个变量?

您可以使用变量记录访问相同的底层内存:

type
  TConverter = record
  case integer of
    0 : (c: cardinal);
    1 : (s: single);
  end;
然后像这样使用它:

var
  converter: TConverter;
  lCardinalVar: cardinal;
  lSingleVar: single;

  converter.c := lCardinalVar;
  lSingleVar := converter.s;
lSingleVar := TConverter(lCardinalVar).s
lSingleVar := PSingle(@lCardinalVar)^;
function ConvertCardinalToSingle(value: Cardinal): Single;
var AsSingle: Single absolute value;
begin
  Result := AsSingle;
end;
或者使用这样的单行类型转换:

var
  converter: TConverter;
  lCardinalVar: cardinal;
  lSingleVar: single;

  converter.c := lCardinalVar;
  lSingleVar := converter.s;
lSingleVar := TConverter(lCardinalVar).s
lSingleVar := PSingle(@lCardinalVar)^;
function ConvertCardinalToSingle(value: Cardinal): Single;
var AsSingle: Single absolute value;
begin
  Result := AsSingle;
end;

我会这样做:

var
  converter: TConverter;
  lCardinalVar: cardinal;
  lSingleVar: single;

  converter.c := lCardinalVar;
  lSingleVar := converter.s;
lSingleVar := TConverter(lCardinalVar).s
lSingleVar := PSingle(@lCardinalVar)^;
function ConvertCardinalToSingle(value: Cardinal): Single;
var AsSingle: Single absolute value;
begin
  Result := AsSingle;
end;
相反的方向是:

lCardinalVar := PCardinal(@lSingleVar)^;

我想不出更直接的方法来实现你的要求。在我看来,它的优点是不需要任何类型或函数定义

您可以编写如下函数:

var
  converter: TConverter;
  lCardinalVar: cardinal;
  lSingleVar: single;

  converter.c := lCardinalVar;
  lSingleVar := converter.s;
lSingleVar := TConverter(lCardinalVar).s
lSingleVar := PSingle(@lCardinalVar)^;
function ConvertCardinalToSingle(value: Cardinal): Single;
var AsSingle: Single absolute value;
begin
  Result := AsSingle;
end;
这里我们使用
absolute
关键字,意思是:变量
value
AsSingle
分配相同的内存。这个关键字被许多人认为是过时的,它肯定是“不安全的”,但它也有它的用途(我喜欢在事件处理程序中使用它来将发送者强制转换为我需要的类型,但无论如何都要先检查)


您不必编写函数,只需让这两个变量在某个点指向一个位置即可。

您可以使用move来复制原始字节:

Assert(SizeOf(CardinalVar) = SizeOf(SingleVar);
Move(CardinalVar, SingleVar, SizeOf(CardinalVar));

您可以通过编写
lSingleVar:=TConverter(lCardinalVar).s来避免局部变量
和编译器将发出一个简单的mov操作,与my中的代码发出的操作相同answer@DavidHeffernan当然我包括了你的建议。在我看来,使用局部变量的例子通常更容易理解,并且使变量零件的内部工作更为明显,所以我将把它留在这里。是的,这些方法基本上都是好的,个人偏好也很重要。实际上,您添加的强制转换方法的一个优点是编译器验证被强制转换的变量与转换器类型的大小相同。我喜欢您的解决方案,因为它是安全的,而且我发现这是最正确的方法。然而,我最终还是使用了David建议的解决方案,因为它可以在现场完成,而无需在其他地方定义任何内容。@Hans没问题:)您可以使用您认为最适合您的情况的任何解决方案。