Board logo

Subject: MicroTip#3 pascal Union 的一个应用 [Print This Page]

Author: skyjacker    Time: 2007-3-19 17:39     Subject: MicroTip#3 pascal Union 的一个应用

MicroTip#3 pascal Union 的一个应用
// Test in Delphi6 up2
// Wrtten by SkyJacker 2007.03.19
// QQ Discuss Group: 130970

1、通过类型转换,实现获取某个字的高低字节。

之前使用字的移位或 Hi,Lo 来得到,Union 也可以阿。

procedure TFrmTest.btnTest(Sender: TObject);
type
  TWordRec = packed record
    case Integer of
      0: (Lo, Hi: Byte); // 先低字节,后高字节(内存实际存放位置)
      1: (Bytes: array [0..1] of Byte); // 先低字节,后高字节(内存实际存放位置)
  end;
var
  H, L: Byte;
  W: Word;
  W2:TWordRec;
begin
  W := $01AA;
  W2 := TWordRec(W);
  H := W2.Hi;
  L := W2.Lo;
  ShowMessage('1. ' + IntToHex(W, 4) + '-' + IntToHex(H, 2) + '-' + IntToHex(L, 2));
end;

Union 还有哪些其他的应用呢?

[ 本帖最后由 skyjacker 于 2007-3-19 17:43 编辑 ]
Author: kendling    Time: 2007-3-20 10:06

我一直都不懂record里的case,其实是什么意思?实际应该怎么写?
Author: Passion    Time: 2007-3-20 10:31

case似乎没起实际作用,只是表示随着case的值不一样而定义的东西也不同。
Author: skyjacker    Time: 2007-3-20 12:15

是啊, case 在编程中没有任何作用.
应该是编译器识别 pascal union 的标志.   

unnion 在 Delphi   中的使用,主要用于兼容不同的类型:
(因为可以使用类型转换TWordRec(), 所以节省空间的作用, 看不出来啊)

var
  Bs: array[0..1] of byte;
begin
  Bs[0] := $AA;
  Bs[1] := $01;
  //W := $01AA;
  W2 := TWordRec(Bs);
  H := W2.Hi;
  L := W2.Lo;
  ShowMessage('1. ' + IntToHex(Word(Bs), 4) + '-' + IntToHex(H, 2) + '-' + IntToHex(L, 2));
end;

=================================================
Delphi SysUtils.pas  中的 Union:
{ Type conversion records }

  WordRec = packed record
    case Integer of
      0: (Lo, Hi: Byte);
      1: (Bytes: array [0..1] of Byte);
  end;

  LongRec = packed record
    case Integer of
      0: (Lo, Hi: Word);
      1: (Words: array [0..1] of Word);
      2: (Bytes: array [0..3] of Byte);
  end;

  Int64Rec = packed record
    case Integer of
      0: (Lo, Hi: Cardinal);
      1: (Cardinals: array [0..1] of Cardinal);
      2: (Words: array [0..3] of Word);
      3: (Bytes: array [0..7] of Byte);
  end;

function TThreadLocalCounter2.HashIndex: Byte;
var
  H: Word;
begin
  H := Word(GetCurrentThreadID);
  Result := (WordRec(H).Lo xor WordRec(H).Hi) and 15;
end;
..............
Author: shenloqi    Time: 2007-3-20 16:01

Union中的case的确没有什么用途,理论上Pascal的编译器应该会根据这个类型进行一些判断的,也就是说如果case的值和能访问的内容是对应的,不过实际上基本上所有的编译器都没有这么做,我想应该是考虑到与C的兼容性吧,毕竟如果加上了这个校验就没有了能和C里面等价的东西了(除了指针操作或者强制转换)。

Union的用途主要在节省内存和与其他语言的交互,有时还有一些特殊的用途,如:Delphi 2007似乎就使用了Union做了一些Hack的事情来保存Vista中的GlassFrame的一些属性的。
Author: kendling    Time: 2007-3-20 23:56

喔喔。。。




Welcome to CnPack Forum (http://bbs.cnpack.org/) Powered by Discuz! 5.0.0