zoukankan      html  css  js  c++  java
  • 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各位.

  • 相关阅读:
    Linux常用命令
    IBM Java多线程 1. 线程基础
    IBM Java多线程 6.其它线程 API 详细信息
    Jakarta Commons Logging学习笔记
    Linux 下存放ssh信息的文件位置
    ArrayList的使用方法
    JAVA基础--JAVA中的反射机制详解
    使用 Bash shell脚本进行功能测试
    log4j详细解
    Eclipse Template用法探讨
  • 原文地址:https://www.cnblogs.com/huangjacky/p/2169521.html
Copyright © 2011-2022 走看看