Delphi XE3 -> 整数到字节数组

问题描述 投票:0回答:6

我有一个数据结构:

data = array of integer;

我已经从

填了它
source = array of byte;

data[x] := Source[offset] or (Source[offset + 1] shl 8) or
    (Source[offset + 2] shl 16) or (Source[offset + 3] shl 24);

处理完这些块后,我必须将它们恢复为“字节”...

有什么想法吗?

arrays delphi integer byte
6个回答
9
投票

你的意思是这样吗?

var
  i: integer;
  b1, b2, b3, b4: byte;
begin
  b1 := byte(i);
  b2 := byte(i shr 8);
  b3 := byte(i shr 16);
  b4 := byte(i shr 24);

例如,尝试一下,

procedure TForm1.FormCreate(Sender: TObject);
var
  i: integer;
  b1, b2, b3, b4: byte;
begin
  i := $AABBCCDD;
  b1 := byte(i);
  b2 := byte(i shr 8);
  b3 := byte(i shr 16);
  b4 := byte(i shr 24);
  ShowMessage(IntToHex(b1, 2));
  ShowMessage(IntToHex(b2, 2));
  ShowMessage(IntToHex(b3, 2));
  ShowMessage(IntToHex(b4, 2));
end;

8
投票

您可以使用 Move 一次性完成此操作。

Move(source[0], dest[0], Length(source)*SizeOf(source[0]));

如果您需要执行网络/主机字节顺序转换,那么您可以在

Move
之后遍历整数数组。

在相反的方向上,你会以相反的方式进行所有操作。

如果您没有遇到字节顺序问题,那么您实际上可能根本不需要转换为字节数组。您可以按原样使用整数数组。请记住,如果没有字节顺序问题,字节数组和整数数组的内存布局是相同的(这就是为什么您能够使用

Move
进行 blit)。


7
投票

嗯...我看到一个使用 Move 的答案和一个使用 shift 的答案,但是简单的转换怎么样?:

var
  I: Integer;
  B: array[0..3] of Byte;
begin
  // from bytes to integer:
  I := PInteger(@B)^;
  // from integer to bytes:
  PInteger(@B)^ := I;

或者使用你的数组:

data[i] := PInteger(@source[offset])^;

反之亦然:

// get low byte
source[offset] := PByte(@data[i])^; // or := PByte(@data[i])[0];
// get second byte
secondByte := PByte(@data[i])[1]; // or := (PByte(@data[i]) + 1)^;

PInteger(@source[offset])^ := data[i];

如您所见,通过转换为指针可以获得很长的路要走。这实际上并不需要指针,编译器足够聪明,可以直接访问这些项目。


0
投票

如评论所述,您不需要移动数据即可以字节和整数方式访问它。

您的原始字节数组可以通过类型转换作为整数数组进行访问。

type
  TArrayInteger = array of Integer;
...
for i := 0 to Pred(Length(source)) div SizeOf(Integer) do
  WriteLn(TArrayInteger(source)[i]);

我经常将这些类型转换隐藏在类中。在 XE3 中,可以为简单类型声明类帮助器,例如字符串、字节、整数等。例如,请参阅 TStringHelper。 简单类型数组也是如此。

这是使用记录助手的示例:

type
  TArrayByte = array of Byte;
  TArrayInteger = array of Integer;

  TArrayByteHelper = record helper for TArrayByte
  private
    function GetInteger(index : Integer) : Integer;
    procedure SetInteger(index : Integer; value : Integer);
  public
    property AsInteger[index : Integer] : Integer read GetInteger write SetInteger;
  end;

function TArrayByteHelper.GetInteger(index: Integer): Integer;
begin
  Result := TArrayInteger(Self)[index];
end;

procedure TArrayByteHelper.SetInteger(index: Integer; value: Integer);
begin
  TArrayInteger(Self)[index] := value;
end;

像这样使用它:

Var
  source : TArrayByte;
  i : Integer;
begin
  SetLength(source,8);
  for i := 0 to 7 do
    source[i] := i;
  for i := 0 to 1 do
    WriteLn(Format('%8.8X',[source.AsInteger[i]]));
  ReadLn;
end.

0
投票

将其构建为函数:

Type TBytes = array of byte;

function InttoBytes(const int: Integer): TBytes;
begin
  result[0]:= int and $FF;
  result[1]:= (int shr 8) and $FF;
  result[2]:= (int shr 16) and $FF;
end;

0
投票

这个问题可能已经有点老了,但对于仍在关注这个问题的所有人来说,我相信最简单的问题是:

var
  Buf: TBytes;
  I: Integer;
begin
  SetLength(Buf, 4);
  for I := 0 to 3 do begin
    Buf[I] := PByte(Value)[I];
  end;
  result := Buf;
end;
© www.soinside.com 2019 - 2024. All rights reserved.