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各位.