现在的位置: 首页 > 综合 > 正文

Delphi – PointerMath编译指令

2011年12月01日 ⁄ 综合 ⁄ 共 1997字 ⁄ 字号 评论关闭

我们知道在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各位.

抱歉!评论已关闭.