• 指针与指针变量(转)


    通常指针变量的使用是:先定义指针变量,后给指针变量赋值,最后引用指针变量。现说明如下:
      (1)定义指针变量
      在变量定义语句int *p, *p1, *q; 中用 * 定义的变量均为指针变量。因此该语句定义了名为p、p1与q三个整型指针变量。因为指针变量用于存放变量地址,而地址通常为4字节,所以指针变量的长度均为4个字节。
      (2)指针变量赋值
      指针变量定义后其值为随机数,若此随机数为系统区的地址,则对该指针变量所指系统区某存储单元进行赋值运算,将改变系统区该单元中内容,可能导致系统的崩溃。所以,指针变量定义后必须赋某个变量的地址或0。
      从上面例子可以看出,给指针变量赋初值有三种情况:
      第一种情况是用取地址运算符"&"将变量地址赋给指针变量。如:p=&a;
      第二种情况是将一个指针变量中的地址赋给另一个指针变量,如:p1=p;
      第三种情况是给指针变量赋空值0,如q=0;表示该指针变量不指向任何变量。
      经过赋值后,使指针变量p、p1指向变量a,q不指向任何单元,如图7.2所示。
      (3)指针变量的引用
      指针变量的引用是通过指针运算符"*"实现。在上例中,*p与*p1均表示变量a,因此,第一个输出语句 cout<<*p 被执行后,输出的是变量a的内容100。而赋值语句 *p1=200;是通过指针变量p1间接的将数据200赋给变量a,因此,第二个输出语句中,a 、*p、 *p1同为赋值后变量a的内容200。
      (4)指针变量初始化
      指针变量可以象普通变量一样,在定义指针变量时赋初值,如上例中,定义指针变量p的语句可写成:int *p=&a;
    7.1.3 指针变量的运算

      指针变量的运算有三种:赋值运算、关系运算与算术运算。
      1.指针变量赋值运算
      指针变量赋值运算就是将变量的地址赋给指针变量,上节内容已介绍过,现再举一例加深读者对指针变量赋值运算的理解。
      【例7.2】定义三个整型变量a1、a2、a3,用指针变量完成a3=a1+a2的操作。再定义两个实型变量b1、b2,用指针变量完成b1+b2的操作。
     # include <iostream.h>
     void main (void)
     { int a1=1,a2=2,a3;
      int *p1,*p2,*p3;
      float b1=12.5,b2=25.5;
      float *fp1,*fp2;
      p1=&a1;
      p2=&a2;
      p3=&a3;
      *p3= * p1 + *p2;
      fp1=&b1;
      fp2=&b2;
      cout<<" *p1="<<*p1<<'\t'<<" *p2="<<*p2<<'\t' <<"*p1+*p2="<<*p3<<'\n';
      cout<<"a1="<<a1<<'\t'<<" a2="<<a2<<'\t' <<"a1+a2="<<a3<<'\n';
      cout<<"b1=" <<*fp1<<'\t'<<" b2="<<*fp2<<'\t'<<"b1+b2="<<*fp1+*fp2<<'\n';
     }
     
      程序执行后,输出:
      *p1=1 *p2=2 *p1+ *p2=3
      a1=1 a2=2 a1+a2=3
      b1=12.5 b2=25.5 b1+b2=38
      在此例中,经过指针变量赋值运算后,整型指针变量p1、p2、p3分别指向变量a1、a2、a3,因此,*p1=a1,*p2=a2,*p3=a3。所以,*p3= * p1 + *p2 操作就是a3=a1+a2 操作。如图7.3(a)所示。
        2.指针变量的算术运算

      指针变量的算术运算主要有指针变量的自加、自减、加n和减n操作。
      (1)指针变量自加运算
      指令格式:<指针变量>++;
      指针变量自加运算并不是将指针变量值加1的运算,而是将指针变量指向下一个元素的运算。当计算机执行 <指针变量>++ 指令后,指针变量实际增加值为指针变量类型字节数,即:<指针变量>=<指针变量>+sizeof(<指针变量类型>)。假设数组a的首地址为1000,如图7.4所示。
    int *p=&a[0]; //p=1000,指向a[0]元素
      p++;
      第一条语句将数组a的首地址1000赋给指针变量p,使p=1000。第二条语句使p作自加运算:
      p=p+sizeof(int)=p+4=1004,使p指向下一个元素a[1] 。
       (2)指针变量自减运算
      指令格式:<指针变量>――;
      指针变量的自减运算是将指针变量指向上一元素的运算。当计算机执行 <指针变量>―― 指令后,指针变量实际减少为指针变量类型字节数,即:
      <指针变量>=<指针变量>―sizeof(<指针变量类型>)
      自加运算和自减运算既可后置,也可前置。
      (3)指针变量加n运算
      指令格式:<指针变量>=<指针变量>+n;
      指针变量的加n运算是将指针变量指向下n个元素的运算。当计算机执行 <指针变量>+ n 指令后,指针变量实际增加值为指针变量类型字节数乘以n,即:
    <指针变量>=<指针变量>+sizeof(<指针变量类型>)*n
      (4)指针变量减n运算
      指令格式:<指针变量>=<指针变量>―n;
      指针变量的减n运算是将指针变量指向上n个元素的运算。当计算机执行 <指针变量>― n 指令后,指针变量实际减少值为指针变量类型字节数乘以n,即:
      <指针变量>=<指针变量>―sizeof(<指针变量类型>)*n
    【例7.3】指针变量的自加、自减、加n和减n运算。假设数组a的首地址为1000,如图7.4所示。

     # include <iostream.h>
     void main( void)
     { int a[5]={0,1,2,3,4};
      int *p;
      p=&a[0]; //p指向a[0],p=1000
      p++ ; //p指向下一个元素a[1],p=1004
      cout<< *p<<'\t'; //输出a[1]的内容1。
      p=p+3; //p指向下3个元素a[4],p=1016
      cout<< *p<<'\t'; //输出a[4]的内容4。
      p――; //p指向上一个元素a[3],p=1012
      cout<< *p<<'\t'; //输出a[3]的内容3。
      p=p―3; //p指向上3个元素a[0],p=1000
      cout<< *p<<'\t'; //输出a[0]的内容0。
     }
      程序执行后输出:
      1 4 3 0
      从上例可以看出,通过对指针变量的加减算术运算,可以达到移动指针变量指向下n个元素单元或向上n个元素单元的目的。
    3.指针变量的关系运算
      指针变量的关系运算是指针变量值的大小比较,即对两个指针变量内的地址进行比较,主要用于对数组元素的判断。

      【例7.4】用指针变量求一维实型数组元素和,并输出数组每个元素的值及数组和。
     # include <iostream.h>
     void main( void )
     { int a[5]={1,2,3,4,5};
      int *p,*p1;
      p1=&a[4]+1;
      for (p=&a[0];p<p1;p++)
      cout <<*p<<'\t';
      int sum=0;
      p=&a[0];
      while (p!=p1) sum+=*p++;
      cout <<"\n sum="<<sum<<endl;
     }
      执行程序后:输出:
      1 2 3 4 5
      sum=15
      程序中首先将数组尾地址+1赋给p1,如图7.4所示。在for 语句中,指针变量p为循环变量,数组首地址&a[0]赋给p。循环时先将循环控制变量p与p1中地址比较,若p<p1,则以*p方式输出数组元素a[i]的值,并将p自加指向下一个元素。此循环直到p≥p1为止。
      在while语句中,仍用p作为循环控制变量,当p!=p1时,用sum=sum+*p;语句将数组元素值累加到sum中去,同时用 p++语句使指针变量p指向下一个元素,循环直到p=p1为止,最后输出数组元素之和。
    4.指针运算符的混合运算与优先级

      (1)指针运算符* 与取地址运算符&的优先级相同,按自右向左的方向结合。
      设有变量定义语句: int a, *p=&a;
      则表达式:&*p 的求值顺序为先"*"后"&",即& (*p)=&a=p 。
      而表达式:*&a 的求值顺序为先"&"后"*",即* (&a)=*p=a 。
      (2)"++"、"――"、"*"、"&"的优先级相同,按自右向左方向结合。下面结合例子加以说明。设有变量定义语句:
      int a[4]={100,200,300,400},b;
      int * p=&a[0];
      为了叙述方便,假设系统给数组a分配的首地址为1000,如图7.4所示。
      ① b=*p++;
      按自右向左结合的原则,表达式 *p++ 求值序顺为先"++"后"*",即:*(p++)。由于"++"在p之后为后置++运算符,所以表达式的实际操作是先取*p值,后进行p++的自加操作。即赋值表达式 b=*p++; 等同于下面两条语句:
      b=*p; // b=*p=a[0]=100
      p++; //p=p+sizeof(int)= 1004
      最后运算的结果为b=100,p=1004指向a[1]。
      ② b=*++p;
      按自右向左结合的原则,表达式 *++p 求值顺序为先"++"后"*",即:*(++p)。由于++在p之前为前置++运算符,所以表达式的实际操作是进行++p的自加操作,后取*p值。即赋值表达式 b=*++p; 等同于下面两条语句:
      ++p; //p=p+sizeof(int)= 1008,指向a[2]
      b=*p; // b=*p=a[2]=300
      最后运算的结果为b=300,p=1008指向a[2]。
    ③ b=(*p)++;
      由于括号内优先运算,所以表达式先取出*p(即a[2])的值并赋给b,然后将*p的值即a[2]内容加1。所以表达式等同于下面两条语句:
      b=*p; //b=a[2]=300
      a[2]++ ; // a[2]=300+1=301
      ④ b=*(p++);
      由①可知,该表达式等同于*p++,运算结果为:
      b=*p; //b=a[2]=301
      p++; // p=p+sizeof(int)=1012,指向a[3]
      ⑤ b=++*p ;
      该表达式先进行"*"运算,再进行"++"运算,即先取出*p的值,再将该值加1。因此表达式实际进行了如下运算:b=++(*p)=++a[3]=400+1=401; p仍指向a[3]不变。
      将上述讨论中各语句汇总为例题如下:

     
      【例7.5】指针运算符"*"、"&"、"++"优先级与结合律示例。
     # include <iostream.h>
     main()
     { int a[4]={100,200,300,400},b;
      int *p=&a[0];
      cout<<'\t'<<"p="<<p<<endl;
      b=*p++;
      cout<<"b="<<b<<'\t'<<"p="<<p<<endl;
      b=*++p;
      cout<<"b="<<b<<'\t'<<"p="<<p<<endl;
      b=(*p)++;
      cout<<"b="<<b<<'\t'<<"p="<<p<<endl;
      b=*(p++);
      cout<<"b="<<b<<'\t'<<"p="<<p<<endl;
      b=++*p;
      cout<<"b="<<b<<'\t'<<"p="<<p<<endl;
      }
      运行结果为:
      p=0x0065FDE8
      b=100 p=0x0065FDEC
      b=300 p=0x0065FDF0
      b=300 p=0x0065FDF0
      b=301 p=0x0065FDF4
      b=401 p=0x0065FDF4
      说明:在定义数组时,数据a的地址是由操作系统存储管理动态分配的,因此,数组a的地址是不确定的,每次运行的结果都可能会不同。一般用十六进制数表示。本例中系统为数组a分配的首地址为0x0065FDE8。而在图7.4中所假设的地址1000~1016完全是为了便于读者理解。
  • 相关阅读:
    泛社交泛泛之交也很重要
    iOS 切后台挂机
    iOS 导航栏translucent用法
    iOS 中UIButton中文字换行
    iOS 给UIimageView添加UITapGestureRecognizer手势点击事件
    iOS15UITableView多了白条,导航栏和Tabbar变成白色和标题变黑处理总结属性变化和原来基本的导航栏属性总结记录(看到就更新)
    iOS延时定时功能
    iOS uiview添加背景图案
    iOS 导航栏返回把样式带回前面怎么办
    iOS 识别图片二维码demo,复制粘贴即用
  • 原文地址:https://www.cnblogs.com/kungfupanda/p/2267825.html
Copyright © 2020-2023  润新知