【问题标题】:Typecasting Cardinal to Single将 Cardinal 类型转换为 Single
【发布时间】:2017-05-09 01:45:47
【问题描述】:

CardinalSingle 都是 4 字节/32 位数据类型,但是当我将它们相互转换时,Delphi 10.1(柏林)出现 Invalid Typecast 错误。

lSingleVar := Single(lCardinalVar);

我不是在谈论两种类型之间的转换,因为它只会存储 23 位基数数据(Single datatype 的小数部分)。我需要将至少 30 位数据存储到 Single 变量中。我有充分的理由(类型不能更改),我很乐意详细说明。

如何对Single 变量进行类型转换?

【问题讨论】:

    标签: delphi delphi-10.1-berlin


    【解决方案1】:

    我会这样做:

    lSingleVar := PSingle(@lCardinalVar)^;
    

    相反的方向是:

    lCardinalVar := PCardinal(@lSingleVar)^;
    

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

    【讨论】:

      【解决方案2】:

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

      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
      

      Variant parts in records

      【讨论】:

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

      你可以这样写一个函数:

      function ConvertCardinalToSingle(value: Cardinal): Single;
      var AsSingle: Single absolute value;
      begin
        Result := AsSingle;
      end;
      

      这里我们使用absolute关键字,意思是:变量valueAsSingle分配相同的内存。这个关键字被许多人认为是过时的,它绝对是“不安全的”,但它有它的用途(我喜欢在事件处理程序中使用它来将 Sender 转换为我需要的类型,但无论如何都要先检查)。

      你不必写一个函数,你可以让这两个变量在某个时间点指向一个地方。

      【讨论】:

        【解决方案4】:

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

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

        【讨论】:

          猜你喜欢
          • 2011-05-17
          • 1970-01-01
          • 2021-03-20
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-04-16
          • 1970-01-01
          相关资源
          最近更新 更多