1. 程式人生 > >再談指標運算和地址加減運算的區別

再談指標運算和地址加減運算的區別

先上程式碼,有下面一段程式碼:

//下面是讀取線狀目標的記錄內容的程式碼:
procedure OnReadLineShp(ShpFileName:String);
var
  FileHandle:integer;
  RecordNumber:integer;
  ContentLength:integer;
  num:integer;
  shapeType:integer;
  Box:array[0..3]of double;
  NumParts:integer;
  NumPoints:integer;
  Parts:^Integer;
  addr:Integer;
  i,j:integer;

  pointNum:integer;
  PointsX:^double;
  PointsY:^double;
begin
       // 開啟座標檔案
       FileHandle:=FileOpen(ShpFileName,fmOpenRead);
       // 讀取座標檔案頭的內容開始
       FileSeek(Filehandle,100,0);
       // 讀取線狀目標的實體資訊

       num   :=0;
       while((FileRead(FileHandle,RecordNumber,    sizeof(int))<>0))do
       begin
              FileRead(FileHandle,ContentLength,sizeof(int));
              RecordNumber      := OnChangeByteOrder (RecordNumber);
              ContentLength       := OnChangeByteOrder (ContentLength);

              FileRead(FileHandle,shapeType,    sizeof(int));   // 讀 Box
              for i:=0 to 3 do
                     FileRead(FileHandle,Box[i],     sizeof(double));   // 讀 NumParts 和 NumPoints
              FileRead(FileHandle,NumParts,     sizeof(int));
              FileRead(FileHandle,NumPoints,    sizeof(int));   // 讀 Parts 和 Points
              GetMem(parts,sizeof(integer)*NumParts);//parts=$65B78, parts^=0x65B64(416612)
              //new(parts);
              for i:=0 to NumParts-1 do
              begin
                //FileRead(FileHandle,Integer(Parts)+i,   sizeof(int));
                //FileRead(FileHandle,PInteger(Integer(Parts)+i),   sizeof(int));//錯誤,第二個引數PInteger(Integer(Parts)+i)表示的是一個地址,
                //addr:=Integer(Parts)+i;//0.9.30版本竟然不支援上面的強制轉換,要用中間變數轉一下??? 其是是自已錯了,對指標不熟,FileRead的第二個引數應為一個buffer緩衝區,而不是一個指標變數,
                //其實用這個語句就行,不用下面的中間變數轉換:FileRead(FileHandle,PInteger(PInteger(Parts+i))^,   sizeof(int));


                addr:=Integer(PInteger(Parts+i));//把Parts指標分配到的地址賦給addr,!!!!!!!!!!!!!!!更奇怪的是addr竟然不等於parts的值:$65B78, 而是等於416632(0x65B78),^_^,等於,看錯了!!!
                //FileRead(FileHandle,PInteger(addr),   sizeof(int));//這裡實際上是把內容讀到了addr變數中
                FileRead(FileHandle,PInteger(addr)^,   sizeof(int));//而要用這個式子才正確,把內容讀到addr代表的地址指向的空間中
                //FileRead(FileHandle,Parts,   sizeof(int));
              end;

              for i:=0 to NumParts-1 do
              begin
                     if(i<>NumParts-1)then
                            //pointNum       :=Parts[i+1]-Parts[i]
                           // pointNum       :=PInteger(Integer(Parts)+i+1-(Integer(Parts)+i) )^//錯誤

                           pointNum       :=PInteger(Parts+i+1)^-PInteger(Parts+i)^//正確
                     else
                            //pointNum       :=NumPoints-PInteger(Integer(Parts)+i)^;//錯誤,這裡變成了地址加i,而不是指標加i,
                            pointNum       :=NumPoints-PInteger(PInteger(Parts+i))^;//正確




                     //PointsX =new double[pointNum];
                     GetMem(PointsX,sizeof(double)*pointNum); //PointsX=$127728
                     GetMem(PointsY,sizeof(double)*pointNum); //PointsY=$1277A8
                for j:=0 to pointNum-1 do
                     begin
                       //inc(PointsX); //$127730
                       //addr:= Integer(PointsX)+j;//錯誤,addr的值應該為下一個PointX的地址:$127730,而這裡變成$127728+1=$127729,
                       addr:= Integer(PInteger(PointsX+j));//應該使用該語句,先用指標變數加j, 然後轉換為Integer整型就可以了,或者先用上面的Inc(PointsX)語句先把指標指向下一個地址,再直接賦值;
                       FileRead(FileHandle,PDouble(addr)^, sizeof(double));
                       addr:=Integer(PointsY)+j;
                       FileRead(FileHandle,PDouble(addr)^, sizeof(double));
                     end;
                     FreeMem(PointsX);
                     FreeMem(PointsY);
              end;
              FreeMem(Parts);
       end;
       FileClose(FileHandle);
end;

  總結,根據上面的分析,在使用指標時,自已的頭腦中一定要清楚:指標變數加減一個數和地址加減一個數是不同的,如果一個浮點數指標變數PointsX的地址為$127728,則PointX+1表示的地址是$127730,代表下一個浮點數的開始地址(假設PointX是一組連續浮點數的開始地址),因為一個浮點數點8個位元組的空間,$127728+8=$127730,而如果 Integer(PointsX)+1,則表示的地址為$127729,是把$127728這個地址進行了加1的操作;