代码之家  ›  专栏  ›  技术社区  ›  Runner

将字节转换为基数的最佳方法是什么,反之亦然

  •  2
  • Runner  · 技术社区  · 16 年前

    我现在有以下代码。

    type
      TByte4 = array[0..3] of Byte; // 32-bit
    
    function CardinalToBytes(const Data: Cardinal): TByte4;
    begin
      Result[0] := (Data shr 24) and 255;
      Result[1] := (Data shr 16) and 255;
      Result[2] := (Data shr 8) and 255;
      Result[3] := Data and 255;
    end;
    
    function BytesToCardinal(const Data: TByte4): Cardinal;
    begin
      Result := (Data[0] * 16777216) +
                (Data[1] * 65536) +
                (Data[2] * 256) +
                 Data[3];
    end;
    

    我想知道这是否是最快和最有效的方法(我确信不是:)。关键是这必须在Delphi2006的紧凑框架下工作(甚至不用问)。 我在TEA加密算法中使用它,该算法与Delphi的ANSI和Unicode版本以及Delphi2006中的.NET和.NET Compact框架一起工作。

    因此,不允许使用指针的“move”和类似函数(不,我不希望使用不安全的代码)。

    编辑:

    我还是找不到更好的方法。有人提出了一些很好的建议,但都在.NET中失败了。恐怕我再也不会在死路上浪费时间了。vcl.net死了,恐怕Delphi的cf也死了。所以这对于维护这个项目是必须的。如果有人证明我错了,让代码在.NET中编译,我还是会等一会儿。

    编辑2:

    解决方案和大多数情况一样简单。有人不得不寻找明显的解决办法。我只是不知道.net上有个bitconverter类

    5 回复  |  直到 16 年前
        1
  •  2
  •   Jon Benedicto    16 年前

    在delphi.net中,使用.NET框架中的bitconverter类进行转换。参见 BitConverter Class (System) .

    举个例子:

    function CardinalToBytes(const Data: Cardinal): TBytes;
    begin
      Result := BitConverter.ToBytes(Data);
    end;
    
    function BytesToCardinal(const Data: TBytes): Cardinal;
    begin
      Result := BitConverter.ToUInt32(Data, 0);
    end;
    
        2
  •  1
  •   GJ.    16 年前

    好吧,这有点快…

    别忘了关闭范围检查!

    function CardinalToBytes(const Data: Cardinal): TByte4;
    begin
      Result[0] := Data shr 24;
      Result[1] := Data shr 16;
      Result[2] := Data shr 8;
      Result[3] := Data;
    end;
    
        3
  •  1
  •   Remko    16 年前

    一种方法是使用案例记录:

    type
      TTestRecord = record
        case Cardinal of
          0: (Card: Cardinal);
          1: (Arr: array[0..3] of Byte);
      end;
    
    var
      TR: TTestRecord;
    begin
    
      TR.Arr[0] := 0;
      TR.Arr[1] := 1;
      TR.Arr[2] := 2;
      TR.Arr[3] := 3;
      TR.Card := 0;
    
        4
  •  1
  •   Marco van de Voort    16 年前

    响应

    结果:=tbyte4(数据);

    和 结果:=基数(数据)

    但是,这不是相同的endianwise(您或多或少实现了一个主机到little endian函数,然后回到上面)。

    另外,还有联合的把戏:

      type 
       TSomeRecord = packed record
                    case boolean of 
                        true : (data4:TByte4);
                        false :(dateabyte:cardinal);
                     end;
    

    但我想.NET也会对此发狂。

        5
  •  0
  •   GJ.    16 年前

    你没有说不记得,所以…

    type
      TByte4 = packed array[0..3] of Byte; // 32-bit
    
    function CardinalToBytes(const Data: Cardinal): TByte4;
    asm
      bswap  eax
    end;
    
    function BytesToCardinal(const Data: TByte4): Cardinal;
    asm
      bswap  eax
    end;