设为首页 加入收藏

TOP

7.5.1 算术运算
2013-10-07 01:12:19 来源: 作者: 【 】 浏览:70
Tags:7.5.1 算术 运算

7.5  指针的运算

指针变量可以像普通变量一样进行运算,但其运算的种类是有限的,而且变化规律要受其所指向类型的制约。一般来讲,它只能进行赋值运算、部分算术运算和关系运算。赋值运算可以参考7.4"初始化"小节,本节主要讲解指针的算术运算和关系运算。

7.5.1  算术运算

指针只能完成两种算数运算:加和减。指针的加减运算与普通变量的加减运算不一样,指针的加减变化规律要受所指向的类型约束。它只能与以整型作为基类型的数据类型进行运算,或者在指针变量之间。指针的运算都是以元素为单位,每次变化都是移动若干个元素位。如果指针与0进行加减运算,这保持原来的指向不变。

指针的加减运算不是单纯的在原地址基础上加减1,而是加减一个数据类型的长度。所以,指针运算中"1"的意义随数据类型的不同而不同。例如指针是整型指针,那么每加减一个1,就表示将指针的地址前或后移动一个整型类型数据的长度,即地址要变化4个字节,移动到下一个整型数据的首地址上。这时"1"就代表4。如果是double型,那么"1"就代表8。

指针的加减运算最好限定在事先申请的内存单元内,不要通过加减运算跨越到其他内存块内。虽然,编译器不会对这个问题报错,但这么做是很危险的。有可能在无意识的情况下访问或破坏了其他内存单元的数据。

指针可以进行加减运算,但两指针之间只能进行减运算。两个指针的减法表示计算它们之间的元素个数。如果差为负数,表示地址高的指针需要后移几次才能到地址低的指针处。如果是正数,表示地址低的指针需要移动几次才能前进到地址高的指针处。这个值实际是指针地址的算术差除以类型宽度得到的。

【示例7-13】 演示指针的加减运算。

  1. int main()  
  2. {  
  3.     int *pInt1=0;  
  4.     int *pInt2=0;  
  5.     int k=0;  
  6.     //申请5个整型存储单元  
  7.     pInt1=new int[5];  
  8.    //保留存储单元的首地址  
  9.     pInt2=pInt1;  
  10.     cout<<"step1:填充申请的存储单元"<<endl;  
  11.     for(int i=0;i<5;i++)  
  12.     {  
  13.         //输出指针的地址  
  14.         cout<<k++<<" -- "<<pInt1<<endl;  
  15.         //赋值  
  16.         *pInt1=2*i;  
  17.         //移动到下一个存储单元  
  18.         pInt1++;  
  19.     }  
  20.     //for循环退出后,pInt1移出了申请的存储单元一个整型长度的空间  
  21.     //为了避免指针指到非法区域,将指针移回申请的存储单元内  
  22.     cout<<"step2:移回到存储单元的最后一个元素上"<<endl;  
  23.     pInt1--;  
  24.     cout<<k++<<" -- "<<pInt1<<endl;  
  25.     cout<<"step3:倒序输出申请的存储单元内容"<<endl;  
  26.     for(int i=0;i<5;i++)  
  27.     {  
  28.         cout<<k++<<" -- "<<*pInt1<<endl;  
  29.         pInt1--;  
  30.         cout<<k++<<" -- "<<pInt1<<endl;  
  31.     }  
  32.     //for循环退出后,pInt1移出了申请的存储单元一个整型长度的空间  
  33.     //为了避免指针指到非法区域,将指针移回申请的存储单元内  
  34.     //pInt1又回到了存储块的首地址处  
  35.     cout<<"step4:移回到存储单元的第一个元素上"<<endl;  
  36.     pInt1++;  
  37.     cout<<k++<<" -- "<<pInt1<<endl;  
  38.     //将pInt2移动到第四个元素上  
  39.     cout<<"step5:将pInt2移动到第四个元素上"<<endl;  
  40.     cout<<" 移动前 "<<pInt2<<endl;  
  41.     pInt2=pInt2+3;  
  42.     cout<<" 移动后 "<<pInt2<<endl;  
  43.     cout<<k++<<" -- "<<*pInt2<<endl;  
  44.     //再移动一个元素  
  45.     cout<<"step6:将pInt2再移动一个元素"<<endl;  
  46.     pInt2++;  
  47.     cout<<" 移动后 "<<pInt2<<endl;  
  48.     //输出两指针的差  
  49.     cout<<"step7:pInt2与pInt1之差"<<endl;  
  50.     cout<<k++<<" -- "<<(pInt2-pInt1)<<endl;  
  51.     //释放  
  52.     delete[] pInt1;  
  53.     pInt1=0;  
  54.     pInt2=0;  
  55.     return 0;  

该示例的可能输出如下所示。

  1. step1:填充申请的存储单元  
  2. 0 -- 0x3e3f68  
  3. 1 -- 0x3e3f6c  
  4. 2 -- 0x3e3f70  
  5. 3 -- 0x3e3f74  
  6. 4 -- 0x3e3f78  
  7. Step2:移回到存储单元的最后一个元素上  
  8. 5 -- 0x3e3f78  
  9. Step3:倒序输出申请的存储单元内容  
  10. 6 -- 8  
  11. 7 -- 0x3e3f74  
  12. 8 -- 6  
  13. 9 -- 0x3e3f70  
  14. 10 -- 4  
  15. 11 -- 0x3e3f6c  
  16. 12 -- 2  
  17. 13 -- 0x3e3f68  
  18. 14 -- 0  
  19. 15 -- 0x3e3f64  
  20. step4:移回到存储单元的第一个元素上  
  21. 16 -- 0x3e3f68  
  22. step5:将pInt2移动到第四个元素上  
  23.  移动前 0x3e3f68  
  24.  移动后 0x3e3f74  
  25. 17 -- 6  
  26. step6:将pInt2再移动一个元素  
  27.  移动后 0x3e3f78  
  28. step7:pInt2与pInt1之差  
  29. 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】

回书目   上一节   下一节

】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇7.5.2 关系运算 下一篇7.13 常见问题及解答

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: