7.5 指针的运算
指针变量可以像普通变量一样进行运算,但其运算的种类是有限的,而且变化规律要受其所指向类型的制约。一般来讲,它只能进行赋值运算、部分算术运算和关系运算。赋值运算可以参考7.4"初始化"小节,本节主要讲解指针的算术运算和关系运算。
7.5.1 算术运算
指针只能完成两种算数运算:加和减。指针的加减运算与普通变量的加减运算不一样,指针的加减变化规律要受所指向的类型约束。它只能与以整型作为基类型的数据类型进行运算,或者在指针变量之间。指针的运算都是以元素为单位,每次变化都是移动若干个元素位。如果指针与0进行加减运算,这保持原来的指向不变。
指针的加减运算不是单纯的在原地址基础上加减1,而是加减一个数据类型的长度。所以,指针运算中"1"的意义随数据类型的不同而不同。例如指针是整型指针,那么每加减一个1,就表示将指针的地址前或后移动一个整型类型数据的长度,即地址要变化4个字节,移动到下一个整型数据的首地址上。这时"1"就代表4。如果是double型,那么"1"就代表8。
指针的加减运算最好限定在事先申请的内存单元内,不要通过加减运算跨越到其他内存块内。虽然,编译器不会对这个问题报错,但这么做是很危险的。有可能在无意识的情况下访问或破坏了其他内存单元的数据。
指针可以进行加减运算,但两指针之间只能进行减运算。两个指针的减法表示计算它们之间的元素个数。如果差为负数,表示地址高的指针需要后移几次才能到地址低的指针处。如果是正数,表示地址低的指针需要移动几次才能前进到地址高的指针处。这个值实际是指针地址的算术差除以类型宽度得到的。
【示例7-13】 演示指针的加减运算。
- int main()
- {
- int *pInt1=0;
- int *pInt2=0;
- int k=0;
-
- pInt1=new int[5];
-
- pInt2=pInt1;
- cout<<"step1:填充申请的存储单元"<<endl;
- for(int i=0;i<5;i++)
- {
-
- cout<<k++<<" -- "<<pInt1<<endl;
-
- *pInt1=2*i;
-
- pInt1++;
- }
-
-
- cout<<"step2:移回到存储单元的最后一个元素上"<<endl;
- pInt1--;
- cout<<k++<<" -- "<<pInt1<<endl;
- cout<<"step3:倒序输出申请的存储单元内容"<<endl;
- for(int i=0;i<5;i++)
- {
- cout<<k++<<" -- "<<*pInt1<<endl;
- pInt1--;
- cout<<k++<<" -- "<<pInt1<<endl;
- }
-
-
-
- cout<<"step4:移回到存储单元的第一个元素上"<<endl;
- pInt1++;
- cout<<k++<<" -- "<<pInt1<<endl;
-
- cout<<"step5:将pInt2移动到第四个元素上"<<endl;
- cout<<" 移动前 "<<pInt2<<endl;
- pInt2=pInt2+3;
- cout<<" 移动后 "<<pInt2<<endl;
- cout<<k++<<" -- "<<*pInt2<<endl;
-
- cout<<"step6:将pInt2再移动一个元素"<<endl;
- pInt2++;
- cout<<" 移动后 "<<pInt2<<endl;
-
- cout<<"step7:pInt2与pInt1之差"<<endl;
- cout<<k++<<" -- "<<(pInt2-pInt1)<<endl;
-
- delete[] pInt1;
- pInt1=0;
- pInt2=0;
- return 0;
- }
该示例的可能输出如下所示。
- step1:填充申请的存储单元
- 0 -- 0x3e3f68
- 1 -- 0x3e3f6c
- 2 -- 0x3e3f70
- 3 -- 0x3e3f74
- 4 -- 0x3e3f78
- Step2:移回到存储单元的最后一个元素上
- 5 -- 0x3e3f78
- Step3:倒序输出申请的存储单元内容
- 6 -- 8
- 7 -- 0x3e3f74
- 8 -- 6
- 9 -- 0x3e3f70
- 10 -- 4
- 11 -- 0x3e3f6c
- 12 -- 2
- 13 -- 0x3e3f68
- 14 -- 0
- 15 -- 0x3e3f64
- step4:移回到存储单元的第一个元素上
- 16 -- 0x3e3f68
- step5:将pInt2移动到第四个元素上
- 移动前 0x3e3f68
- 移动后 0x3e3f74
- 17 -- 6
- step6:将pInt2再移动一个元素
- 移动后 0x3e3f78
- step7:pInt2与pInt1之差
- 18 - 4
分析:该示例定义了两个指针变量,申请了5个单位的整型存储单元,分别考察了指针的加减运算和指针间的减运算。首先用new运算符申请了5个单位的整型存储单元。由于填充存储单元时,需要移动指针,所以将申请的存储单元的首地址保留下来,这由语句"pInt2=pInt1;"来完成。接下来用for循环给每个存储单元赋值,用"pInt1++;"实现指针的移动,一次一个元素。在for语句内还依次输出了5个存储单元的首地址。从第0~4个单元的输出可以看出,指针的加法是以元素为单位,加1就表示地址要移动sizeof(int)个字节。
分析循环语句可知,从循环退出后指针将移出存储单元一个元素的长度,因此需要移回来。这用语句"pInt1--;"实现。接下来又按倒序输出了存储单元中的内容,如输出中第6~15行所示。注意到第15个输出的地址不再存储单元内,其原因与前一个循环一样,同样需要移回。
第五步将pInt2后移了四个元素。此时,pInt2在第一个元素上。由于计算机中元素的计数是从0开始,所以移到第四个元素需对pInt2加3,即移动3次。对照移动前后的地址和第0~4的输出可看出,3在这里代表了3*sizeof(int)个字节。然后对pInt2又移动了一个元素,到了存储单元的末尾元素上。此时pInt1在首元素上,故两指针的差为4,表示pInt1需要移动4次才能移到pInt2处。
【责任编辑:
云霞 TEL:(010)68476606】