Delphi从字节到结构

时间:2012-04-09 08:39:15

标签: delphi

我有下一个代码:

type THead = packed record
  znmpc: byte;
  znmpcch: array [0..1] of char;
  znc, zneispr, zkpd, zkps, nd: byte;
  zb9, zb10, zb11, zb12, zb13, zb14, zb15: byte;
end;

procedure TForm1.FormCreate(Sender: TObject);
var
  db: ^THead;
  a: array [0..9] of byte;
begin
  a[7] := 9;
  db := @a;
  ShowMessage(IntToStr(db.nd));
end;

这段代码安全吗?我担心接下来的事情:结构的大小超过缓冲区的大小,我担心它。 nd之后struct的成员值对我没有意义。我想知道这段代码可以在某些情况下抛出异常,如果是这样的话吗?

2 个答案:

答案 0 :(得分:6)

如果你仔细处理,我猜它是绝对安全的。但您需要确保不要忘记您可能无法访问zb11..zb15。此外,回想一下,char在Delphi 2009之前是1个字节,在Delphi 2009和更高版本中是2个字节。此外,也许值得制作记录packed(在这种情况下不要认为你需要那个,但是迂腐显然从来都不错)?最后,当然你必须小心,以便数组不会超出范围!

答案 1 :(得分:2)

我想读db.nd很好。您将访问不属于您的堆栈中的某个位置。但是对这个变量写一些东西会导致灾难性的失败,我们无法知道。

另外,如果你的边界过多,你也可能会因为阅读而违反访问权限:

procedure TForm2.Button1Click(Sender: TObject);
var
  db: THead;
  p: PByte;
begin
  db.nd := 9;
  p := @db;

  ShowMessage(IntToStr(p[7])); // shows 9
  ShowMessage(IntToStr(p[700])); // shows 182 for me?
  ShowMessage(IntToStr(p[70000])); // shows 0
  ShowMessage(IntToStr(p[700000])); // access violation!
end;

使用工会更安全:

type
  THead = packed record
    znmpc: byte;
    znmpcch: array [0..1] of AnsiChar;
    znc, zneispr, zkpd, zkps, nd: byte;
    zb9, zb10, zb11, zb12, zb13, zb14, zb15: byte;
  end;

  THeaderUnion = packed record
    case Integer of
      0: (Head: THead);
      1: (ByteArray: Array[0.. sizeof(THead)-1] of Byte);
  end;

procedure TForm1.Button1Click(Sender: TObject);
Var
  db: THeaderUnion;
begin
 db.ByteArray[7] := 9;
 ShowMessage(IntToStr(db.Head.nd));
end;