Delphi - PointerMath编译指令

我们知道在C和C++里面声明一个指针,但是可以像数组一样去访问里面的成员.

在Delphi2009之后我们有了{$POINTERMATH ON}编译开关,我们也可以了.
一般在Delphi2009之前的版本中,我们会用如下几个方法:

1

   1: var
   2:   P: PByteArray;
   3: begin
   4:   P:= PByteArray(某指针);
   5:   P^[0]:= 1;
   6:   P^[1]:= 2;
   7:   ...
   8: end;

2

   1: var
   2:   P: PByte;
   3: begin
   4:   P:= PByte(某地址);
   5:   P^:= 1;
   6:   P:= PByte(Integer(P)+需要偏移的地址);
   7:   P^:= 2;
   8:   ...
   9: end;

3

   1: var
   2:   P: PByte;//或者PChar也可以
   3: begin
   4:   P:= PByte(某地址);
   5:   P^:= 1;
   6:   Inc(P);   //地址+1
   7:   P^:= 2;
   8:   Dec(P);   //地址-1
   9:   P^:= 2;
  10: end;

在用第2 和 3方法的时候,如果内存空间不是我们例子上面转换过来,而是自己申请的,那么释放的时候,请记得偏移后的指针一定要归位,所以一般在偏移前,我们会用一个临时变量来存放指针的初始位置.切记.

好,现在说说Delphi2009中POINTERMATH的用法:

   1: {$POINTERMATH ON}
   2: procedure TForm4.btn1Click(Sender: TObject);
   3: var
   4:   P: PByte;
   5: begin
   6:   GetMem(P, 4);
   7:   try
   8:     //01 03 05 07
   9:     P[0]:= 1;
  10:     P[1]:= 3;
  11:     P[2]:= 5;
  12:     P[3]:= 7;
  13:     //$07050301
  14:     ShowMessage(IntToHex(PInteger(P)^,8));//07050301
  15:   finally
  16:     FreeMem(P);
  17:   end;
  18: end;
  19: {$POINTERMATH OFF}

和C++就一样了.
自己定义的结构体也可以.

   1: type
   2:   PRect = ^TRect;
   3: var
   4:   P: PRect;
   5: begin
   6:   GetMem(P, 4 * SizeOf(TRect));
   7:   try
   8:     //01 03 05 07
   9:     P[0].Left:= 12;
  10:     P[1].Top:= 22;
  11:     P[2].Right:= 32;
  12:     P[3].Bottom:= 42;
  13:     //$07050301
  14:     ShowMessage(IntToStr(P[2].Right));//07050301
  15:   finally
  16:     FreeMem(P);
  17:   end;
  18: end;
  19: {$POINTERMATH OFF}

再看一个有用的.下面是用GDIPlus对图像进行均值灰度化.

   1: uses
   2:   GdiPlus,GdiPlusHelpers;
   3:  
   4: {$R *.dfm}
   5: type
   6:   PABGR = ^TABGR;
   7:   //像素点的4个通道
   8:   TABGR = record
   9:     B,G,R,A: Byte;
  10:   end;
  11: {$POINTERMATH ON}
  12: procedure TForm4.btn1Click(Sender: TObject);
  13: var
  14:   B: IGPBitmap;
  15:   RC: TGPRect;
  16:   BD: TGPBitmapData;
  17:   P: PABGR;
  18:   I,J: Integer;
  19: begin
  20:   B:= TGPBitmap.Create('C:\1.png');
  21:   RC.Initialize(0,0,B.Width, B.Height);//需要处理的图像的区域
  22:   //因为我们结构体定义的是4个字节的ABGR的,所以第3个参数必须是PixelFormat32bppARGB
  23:   BD:= B.LockBits(RC, [ImageLockModeRead, ImageLockModeWrite], PixelFormat32bppARGB);
  24:   try
  25:     P:= PABGR(Bd.Scan0);//实际像素区域.
  26:     for I := 0 to BD.Width * BD.Height -1 do
  27:     begin
  28:       J:= (P[I].B + P[I].G + P[I].R) ;//防止溢出
  29:       P[I].B:= J div 3;
  30:       P[I].G:= P[I].B;
  31:       P[I].R:= P[I].B;
  32:     end;
  33:   finally
  34:     B.UnlockBits(BD);
  35:   end;
  36:   Form4.Canvas.ToGPGraphics.DrawImage(B,10,10);//画出灰度化的图像
  37: end;
  38: {$POINTERMATH OFF}

实验发现在GDIPlus中我们必须用4字节的结构体,Packed Record的3字节的结构体会报错.

今天就只说这么点儿了.byebye各位.

posted @ 2011-09-07 10:29  HuangJacky  阅读(885)  评论(0编辑  收藏  举报
AdminLogin