再谈指针运算和地址加减运算的区别
2012-08-31 09:59
162 查看
先上代码,有下面一段代码:
//下面是读取线状目标的记录内容的代码:
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的操作;
//下面是读取线状目标的记录内容的代码:
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的操作;
相关文章推荐
- C语言数组和指针的理解_在取地址运算上的操作_指针加减操作_a 和&a 的区别
- 指针和指针变量的区别及取地址符的使用
- 详解C++中指针(*)、取地址(&)、解引用(*)与引用(&)的区别
- 值加减,别忘可能是个指针运算
- 1)算术运算;2)指针地址操作;3)位运算 不使用第三方变量交换两个变量的值
- C++ 指针加减运算
- 指针的加减运算
- 指针和指针运算符一起时的运算规则(比如*p++和*++p的区别)
- C++编程入门系列之二十七(数组、指针和字符串:指针变量的声明、地址相关运算--“*”和“&”)
- c语言的 地址运算符 & 和 指针运算符* 的区别
- 指针的点运算和箭头运算(->)的区别
- 详解C++中指针(*)、取地址(&)、解引用(*)与引用(&)的区别 (完整代码)
- C指针地址运算
- C语言指针类型、指针大小、指针所指元素大小、指针加减运算
- char * 与 char [] 区别,char *[] 与 char[][]区别。字符串指针的数组与二维char数组区别。字符串常量赋予指针与字符数组区别。"字符串"等价于其首元素"字"的地址
- 【C语言学习笔记】指针的“加减”运算
- 一、初级篇——指针(*)、取地址(&)、解引用(*)与引用(&)的区别
- 指针(地址)运算
- 指针、数组名、地址的区别
- c语言指针和地址中 &a 和*a 有啥区别