首页 伟德体育app下载官网 编程 必备知识 搜索引擎
站内搜索
  • 最近浏览
  • [J2EE]J2EE 应用伟德体育app下载官网技术
  • MySql替换伟德始于英国1946内容
  • IIS 7 下限制站点带宽和...
  • [伟德始于英国1946]sql serve...
  • linkd.exe目录映射工...
  • thinkphp提示PHP ...
  • [web站点]在IIS上开设...
  • [网络伟德体育app下载官网]如何保证伟德体育app下载官网...
  • dedecms网站写权限
  • MYSQL启用日志,查看日志...
  • thinkphp的设置方法
  • [伟德始于英国1946]查看sql ser...
  • VC++ 重启服务,停止服务...
  • 微软IE 7浏览器曝出第二个...
  • 微软承认系统严重漏洞 Win...
  • 推荐文章
  • [网络伟德体育app下载官网]如何保证伟德体育app下载官网...
  • [伟德始于英国1946]查看sql ser...
  • MySql替换伟德始于英国1946内容
  • thinkphp的设置方法
  • 命令行下的ip安全策略
  • 热文排行
  • API之SetWindows...
  • StartServiceCtrlDispatcher
  • [网络伟德体育app下载官网]如何保证伟德体育app下载官网...
  • 搭建eclipse+Jbos...
  • VC++ 重启服务,停止服务...
  • 远程桌面连接日志脚本bat&vbs
  • VB API 重启服务,停止...
  • 端口复用技术与实现代码(C++)
  • 获取计算机信息有关的API
  • WTS系列函数的使用
  • [web站点]在IIS上开设...
  • 将STL改成链表式
  • vc编译exe的体积最小优化
  • VB ListView的使用
  • [伟德始于英国1946]查看sql ser...
  • 第十九章 指针一 基本概念


    19.1 指针是什么?

    19.2 指针的大小

    19.3 定义一个指针变量

    19.4 初始化指针变量

      19.4.1 指向不明的指针

      19.4.2 给指针变量赋值

    19.5 地址解析 及其操作符 *

    19.6 上机实验一 指向普通变量的指针和指针之间的互相赋值

    19.7 上机实验二:改变指针所指变量的值,改变指针的指向

    19.8 指针的加减操作

      19.8.1 指向数组的指针

      19.8.2 上机实验三:指向数组的指针

      19.8.3 偏移指针

      19.8.4 上机实验四:指针的最小移动单位

      19.8.5 指针的 += 、 -= 、++、 -- 操作

      19.8.6 上机实验五:指针的前置++与后置++的区别

      19.8.7 * (地址解析符)与 ++ 的优先级

      19.8.8 上机实验六:指针的 ++与--操作

    19.9 小结

     

    19.1 指针是什么?

     

    当我们说“人”这个词时,有时指的是“人类”如:“人是一种会笑的动物”,有时则指个体:比如“张三这人”。

     

    “指针”这个要念也一样,它可以意指“指针类型”,也可以代表某个具体的“指针变量”。下面我们重点要讲的是:“什么叫指针变量”。

     

    所以这一小节的题目其实应是:“指针变量是什么?”

     

    “指针变量”是什么?诚如其名,它首先是一个变量。

     

    变量最重要的特性是什么?那就是它可以存储一个值。比如:

     

    下面是三行代码,行号是我为了表达方便而特意加上的,并不在实际代码中出现。

     

    (1)   int a;

    (2)   a = 100;

    (3)   a = 200;

     

    第(1)行定义了一个变量:a。现在它存储的那个值的大小是不定的,因为我们还没有赋给它具体的值呢。

    到了(2)行执行以后,a 就存了一个值,这个值多大?答:100。

    这里举的是一个整型变量,但其实无论是什么类型的变量,都是用来存值的。

    并且,变量的值可以在以后改变大小,比如第(3)行,a中存放的值成了200。

     

    回忆完普通变量的特性,现在说“指针变量”。

     

    指针也是变量,所以也是用于存储一个值。重点是,它存储的这个值,意义有点特别。

     

    指针存储的不是普通的一个值,而是另外一个变量的地址。

     

    一句话:指针是一种用于储存“另外一个变量的地址”的变量。或者拆成两句:指针是一个变量,它的值是另外一个变量的地址。

     

    这就是指针变量与其它的变量的同与不同:的都是一个变量,都用来存储一个值;但,指针存放的是另外一个变量的地址

     

    可以这样打个比方:

     

    有一间房子,它的地址是:人民路108号。这个房子相当于一个变量。那么:

    一、如果它是普通变量,则房子里可能今天住的是张三,明天住的是李四。张三,李四就是这个变量的值。通过访问这间房子,我们可以直接找到张三或李四。

     

    二、如果它是一个指针变量,则房子里不住具体的人,而是放一张纸条,上面写:“南京东路77号”。

    “南京东路77号”是一个什么东西?是一个地址。

    通过该地址,我们继续找,结果在“南京东路77号”里找到张三。

    变量的存储的值可以改变,指针变量的值同样可以变更:

    过一天,我们再去访问这个房子,纸条变了“珠海路309号”,通过它,我们找到的是另一个人。

     

    图解:

     

    能够说出图中两个“20000007”的关系吗?

     

    本质就这点不同,同样是变量,同样要占用一定大小的内存空间,不同的是普通变量在那个内存里,存储了一个具体的值;而指针变量存放的是另一个变量的地址。

     

    不过,什么叫“变量的地址”?只要你是一直跟着我们的课程学习到这里,相信你能明白什么叫变量的“地址”。否则,您可以需要从第一章从头看起了。

     

    说到这里,我们其实一直在说的是“指针变量”,而不是“指针类型”。指针也需要类型,它所存储的那个变量类型,就称为指针的类型。继续前面的比方,有一天我们去人民路108号,今天纸条写着的地址是:“美眉街8号”,于是我们兴冲冲地去了……结果“美眉街8号”里住着一头猪!是不是很失落——我们以为是“人类”,并且是“美眉”,未料却关着一头“猪类”?!

     

    计算机虽然不懂得什么叫“失落”,但为了它的准确性,我们需要事先定义好一个指针到底是放的是什么类型的变量。这个类型通常也当作是该指针的类型。

     

    “指针变量中存储某变量的地址”这种说法是不是有些绕?所以有一个简短的说法:“指针指向某一变量”。

     这种说法的缺陷是不能像第一种说法好样道出指针的本质。但它确实方便。下面我们将不断的使用这两种说法,大家需要知道它们具有相同意义。

     

    19.2 指针的大小

     

    指针的大小是问:一个指针变量占用多少内存空间?

     

    分析:既然指针只是要存储另一个变量的地址,。注意,是存放一变量的地址,而不是存放一个变量本身,所以,不管指针指向什么类型的变量,它的大小总是固定的:只要能放得下一个地址就行!(这是一间只有烟盒大小的“房间”,因为它只需要入一张与着地址的纸条)。

     

    存放一个地址需要几个字节?答案是和一个 int 类型的大小相同:4字节。

     

    所以,若有:

    int* pInt;

    char* pChar;

    bool* pBool;

    float* pFloat;

    double* pDouble;

     

    : sizeof(pInt)、sizeof(pChar)、sizeof(pBool)、sizeof(pFloat)、sizeof(pDouble)的值全部为:4。

     

    (你敢拆电脑吗?拆开电脑,认得硬盘数据线吗?仔细数数那扁宽的数据线由几条细线组成?答案:32条,正是 4 * 8)。

     

    我们这一章有很多上机实验。这就算是第一个,只是我提供了代码:请写一个程序,验证上面关于sizeof(T *)的结论。在写程序之前,务必要先参考一下“数据结构”这一章中sizeof的例子。

     

    19.3 定义一个指针变量

     

    数据类型*  变量名;

    或:

    数据类型  *变量名;

     

    和申请一个普通变量相比,只是在数据类型后面多了一个星号。比如:

     

    int* p;

     

    星号也可以靠在变量名前面,如:

     

    int *p;

     

    要同时定义多个相同类型的指针,则为:

     

    int *p1, *p2;

     

    注意,每个变量之前都必须有 * 。

     

    19.4 初始化指针变量

    是变量就存在一个初始化的问题。一个不能确定是住着什么人的房间,总是有点恐怖。

     

    19.4.1 指向不明的指针

    我先定义一个整型指针:

    int* p;

     

    现在,p是一个指针,int 规定它只能存放整型变量的地址,而不是其它如字符型,布尔型等等。

    我们称:p 是一个整型指针。

     

    不过,现在 p 指向哪里 (即:p 存储的是哪个变量的地址 )?

    变量在没有赋值之前,其值不定的。对于指针变量,值不定可以表述为:指向不明。

     

    重点来了! 一个指向不明的指针,是一个危险的家伙。很多软件有BUG,其最后的原因,就在这里。

    来看看下而的“恐怖片”:

     

    你来到一间阴森森的房间,这房间里有一张纸条 ---> 打开火折,但见

    纸条内容:“XXX街3K号

    ---> 你前往这纸条的神秘地址…… ---> “XXX街3K号”里住着一千年老妖!你……
    程序访问了一个没有初始化的指针:

    int* p;

    p 的内存是随机的一个数,比如: 0x3FF0073D 程序随即访问内存地址:

     0x3FF0073D

    0x3FF0073D 是哪里的内存?说不定正好是Windows老大要用的内存,你竟敢访问!

    Windows一生气,蓝屏。

                         

     

    既然没有赋值的指针这么危险,下面来看看如何给指针赋值。

     

    19.4.2 给指针变量赋值

    (1)        int k = 100;

    (2)        int* p;

    (3)        p = &k;   //p取得变量k的地址 (也称:p指向k)

     

    第1行定义一个整型变量k。

    第2行定义了一个整型指针p。

    而第3行,“指针 p 存储了变量k的地址”。短的说法是“p指向了k”。

     

    执行了上面三行代码后,结果是: p 指向 k。我们来看具体的内存示意图。

     

    p 指向 k 示意图

     

    上图中,红色数字代表什么?红数字11000002 是 变量 k 的内存地址。

     

    指针初始化的结果,就是让它存储下另一个变量的地址。简称指向另一个变量。

     

    下面说说三种常见的,给指针赋值的操作:

     

    一、用 & 取得普通变量的地址。

     

    要想让指针指向某个普通变量,需要通过 & 来得到该普通变量的地址。

     

    int k;

    int* p = &k;

     

     

    二、指针之间的赋值。

    两个指针之间也可以相互赋值,此时不需要通过 & 来取址。

     

    int k;

     

    int* p1

    int* p2;

     

    p1 = &k;  //p1 先指向 k

    p2 = p1;  //然后 ,p2 也指向 k。

     

    注意,p2 = p1的结果是:让p2也指向“p1所指的内容”,而不是让p2指向“p1本身”。

    上面的情况可以改为直接在定义时就赋值:

    int k;

     

    int* p1 = &k;

    int* p2 = p1;

     

    三、让指针指向数组

    数组本身就是地址,所以对数组变量也不用通过 & 来取址。

     

    char name[] = "NanYu";

    char* p = name;  //不用取址符 &

     

    或者:

     

    int arr[3] = {100,99,80};

    int* p = arr; 

     

    四、让指针指向一个新地址

     

    前而的赋值方法都是让指针指向一个已有的内存空间的地址。比如:int* p = &k; 指针变量p 存放的是已有的变量k的地址。其实指针也可以指向一个新开辟的内存空间,这一内存空间不归属于其它变量。

     

    在C++中,常用一个关键字:new 来为指针开辟一段空间。比如:

     

    int* p = new int;

     

    现在,指针变量p存储着一个内存地址,该内存地址确实存在——它是由 new 操作符申请而得。可以这样认为,new 是一位特权人物,不通过它,指针只能指向已有的“房间”;而使用了它,则可以要求系统为指针“新开辟一片空地,然后建上新房间”。

    有特权的人不仅仅是“new”,还有几个系统定义的函数,及Windows提供的函数,都可以实现“向系统要空间”的功能。我们将在后面专门的 章节详细讲解。

     

    19.5 地址解析 及其操作符 *

     

    * 在C,C++语言里除了起“乘号”的作用以外,前面我们还刚学了它可以在定义变量时,表明某个变量是属于“指针类型”。现在,则要讲到它还能起“地址解析”的作用。

     

    什么叫“地址解析”?假设有一 int 类型变量k:

     

    int k = 100;

     

    内存 内存地址
    100 11000000

     

    方框是变量k所占用的内存。100 是该内存中存放的。而 11000000 则是该内存的地址。

     

    “地址解析”就是 地址-> 的解释过程。即:通过地址 11000000 得到位于地址的变量。

    可见“地址解析(*)” 和 “取址(&)” 正好是一对相反的操作。

     

    这好有一比:地址解析符 * 是个邮递员,他要根据信封上的地址,找到实际的房子。而 取址符 & 则是当初到你家抄下门牌号的人。

     

    看一下实际应用例子:

     

    int k = 100;

    int* p = &k;

    int m = *p;

     

    cout << m << endl;

     

    执行以上代码,屏幕上将输出 100。

    实际上也可以这样写,以取得相同结果:

     

    int k = 100;

    int* p = &k;

     

    cout << *p << endl;

     

    直接输出 *p 即可。*p 的值就是 100.

     

    明白了吗? p = &k 让p得到k的地址,而 *p 则得到k的值。

    下面就考一考你 & * 的作用。

     

    int k = 100;

    cout << *&k << endl;

     

    将会输出什么?

     

    通过地址解析得到变量,不仅仅可以“得知”该变量的值,还可直接修改该变量的值。

     

    int k = 100;

    int* p = &k; //p 指向k

     

    *p = -100;

    cout << k << endl;

     

    屏幕上将输出 -100。

     

    19.6 上机实验一 指向普通变量的指针和指针之间的互相赋值

     

    实验一有多个步骤。

     

    第一步、将上面的代码片段变成程序。请大家打开CB,新建空白控制台工程,然后输入以下代码。

     

    1) int k = 100;

    2) int* p1 = &k;

     

    3) cout << *p1 << endl;

     

    4) system("PAUSE");

     

    (行前的编号是为下面讲课方便,你当然不能将它们输入到CB中去。)

     

    运行将查看结果。然后按任意键退出该程序。下面我们要亲眼看看,指针变量p1,是否真的存放着普通变量k的地址。

     

    把断点设在第2行上。(输入光标移到第二行,然后按F5)

    (设置断点)

     

    按F9运行,程序停在断点上,然后按 Ctrl + F7 调出"Evaluate/Modify" 对话框。该对话框可以在程序运行时观察或强行修改某个变量的值。我们这里仅是想看看变量 k 的地址。所以如图输入 &k ,回车后,Result(结果)栏出现:0012FF88。这就是k的地址。

     

    (&k 的值就是 k 的内存地址)

     

    接下来我们该看 p1 的值。看它是否等于 0012FF88。删除 &k ,改为 p1,回车,怎么回事?CB竟然很不配合地显示p1的值为 00000100 ?呵,这是因为当前断点那一行还没有运行呢,p1现在的值是随机的,这验证好我们前面说的“指向不明”。

    (还没有初始化的指针p1,随随便便指向一个莫名的地址)

     

    关掉该对话框,然后按F8再运行一步。再按 Ctrl + F7 调出上面窗口,输入 p1,回车,这回显示的的值正合我们的推想。

    (p1 的值,就是 k 的地址,即:p1 等于 &k

     

     

    第二步、基于前一题,再加上一个指针变量,叫 p2

     

    1) int k = 100;

    2) int* p1 = &k;

    3) int* p2 = p;

     

    4) cout << *p1 << endl;

    5) cout << *p2 << endl;

     

    编译并运行,观察结果应发现,*p *p2 值相等,为什么?因为二者指向同一变量:k。

     

    第三步、请像第一步一样,观察,k 的地址,及p1, p2 的值。看三者是否相等。

     

    最后,将后面的两行输出删除,改为以下两行代码。第一行输出 k 的地址、p1、p2的值。

    第二行 输出k的值、*p1、*p2 值。

     

    //cout << *p1 << endl;

    //cout << *p2 << endl;

     

    cout << "&k = " << &k << ", p1 = " << p1 << ", p2 = " << p2 <<endl;

    cout << "k = " << k << ", *p1 = " << *p1 << ", *p2 = " << *p2 <<endl;
     

     

    运行后结果如下:

    (1245064 是十进制的,它等于十六进制的 0x0012FF88)

     

    19.7 上机实验二:改变指针所指变量的值,改变指针的指向

     

    尽管在上面的例子中修修改改也能改成本例,不过枝节太多的代码不会混淆了我们的目的。这次我们重点在于“改变”。

     

    第一步、 通过指针,改变其所指向的变量的值。(好绕啊!代码却很简单)

     

    int k = 100;

     

    int* p = &k;

     

    //先输出一开始的k和*p的值(用逗号分开)

    cout << k << "," << *p << endl; 

     

    //现在直接改变k值:

    k = 200;

     

    //输出此时的二者的值:

    cout << k << "," << *p << endl; 

     

    //然后通过指针来改变k值:

    *p = 300;

     

    //输出此时的二者的值:

    cout << k << "," << *p << endl; 

     

    system("PAUSE");

     

    输出将是:

     

     

    可见,当p指向k以后,修改 *p 的值完全等同于直接修改 k值。

     

    第二步、改变指针的指向

     

    所谓的“改变指向”,其实就是“改变指针变量中存储的值(另一个变量的地址)”。我们一开始说的,两种不同的说法而已。

    在前面的代码最后,我们加上以下代码:

     

    ...

    int m = 1000;

     

    //现在p改为指向变量 m :

    p = &m;

     

     k = 400;

    cout << k << "," << m << "," << *p << endl;
     

    *p = 2000;

    cout << k << "," << m << "," << *p << endl;

     

    system("PAUSE");

     

    屏幕输出是:

     

    当p改为指向m以后,之前指向的k便再也和它没有什么关系了。改变k值不会再影响p;而改变p值,则影响到m值而非k值。

     

    19.8 指针的加减操作

    整型变量可以加减,求和,求差:

    int a = 100;

    int b = 99;

    int c = a - b;

     

    而指针,由于它存的是一个内存地址,那么我们可以想到,对两个指针进行求和,求差,是没有意义的。想想,把你家的门牌号(206)和对面的的门牌号(207)相加(413),得到的数有什么意义吗?

     

    那么,指针的加减指什么呢?主要是指移动(而不是联通:()。比如,你家是206,那么,你的下一家,应该是206 + 1 = 207,而上一家则是206 - 1 = 205。你会说,我们这里的门牌号不是这样编的。但不管如何,大致应当是一个等差关系,或其它规律。都可以通过不断加上一个数,来得到下一家。

     

    19.8.1 指向数组的指针

     

    现在,来说说指针指向一个数组的情况。

     

    int arr[] = {1,2,3,4,5}; //一个数组

     

    int* parr; //一个指针。

     

    parr = arr; //没有 & ?对啊,对数组就是不用取址符。

     

    cout << *parr << endl;  //输出 *parr

     

    先猜想一下,输出结果是什么?

     

    最“直觉”的想法是:parr 指向一个数组,那么输出时,自然是输出数组中的所有元素了。所以答案应该是:“12345”了?

    不过,我想,学过前面的数组,我们就能知道这种想法错误。

     

    正确答案是输出数组中的第一个元素: 1 。

     

    接下来,如果是这样输出呢?

     

    parr = arr;

    cout << parr << endl;

     

    答案是输出了arr的地址。就等同于输出 arr

    cout << arr << endl; 的作用

     

    在这里,难点是要记住,数组变量本身就是地址。所以有:

     

    1、想让指针变量存储一个数组的地址(想让指针变量指向一个数组)时,不用取址符。

    2、解析一个指向数组的指针,得到的是数组的第一个元素。

     

    我们来看示意图:

     

    (指向数组的指针)

     

    尽管数组中的每一个元素都有自已的地址,然而一个指向数组的指针,它仍然只是存储数组中第一个元素的地址。复习数组的章节,我们知道,数组中第一个元素的地址,就是数组的地址。即上图中的 10000010

     

    事实上,如果我们想故意让代码很难理解,则对于这一句:

     

    parr = arr;

    可以改为:

    parr = &arr[0];

     

    本来嘛, arr 和 &arr[0] 的值就相等,我们在数组的章节已经学过。你若不信,可以输出一个:

    cout << arr << "," << &arr[0] << endl;

     

    19.8.2 上机实验三:指向数组的指针

     

    int arr[2] = {1,2};

    int* p = &arr[0];

     

    //输出:指向数组的指针,数组的地址,数组中第一个元素的地址。

    cout << p << "," << arr << "," << &arr[0] << endl;

     

    system("PAUSE");

     

    结果是:

    (指向数组的指针,数组的地址,数组中第一个元素的地址。)

     

    19.8.3 偏移指针

     

    请看前图的这一部分:

     

    parr 中存的值为 “10000010”。

     

    指针可以进行加减操作。假设我现在再定义一个指针:

     

    int* parr2;

     

    parr2 = parr + 1;

     

    现在问,parr2 的值是多少?有两种答案。一种说, parr 存的值是 10000010 ,加1后,自然应为 10000011了。这看似自然的答案又是错误了。

     

    正确答案:10000014。继续看前图另一小部分:

    (加1后,指针指向了下一个元素)

     

    加1后,指针指向了下一个元素。由于这是一个 int 类型的数组,每个元素的大小是4个字节。所以第二个元素的地址是10000014。

     

    重点 & 易错点:对指针 进行加1操作,得到的是下一个元素的地址,而不是原有地址值直接加1。

     

    知到了如何“加”,也就知道了如何“减”。减以后,得到的是上一个元素的大小。

     

    所以,一个类型为 T 的指针的移动,以 sizeof(T) 为移动单位。

     

    比如:

    int* pInt; 移动单位为 sizeof(int) 。即:4。而 char* pChar; 移动单位为 sizeof(char)。即1。

     

    试举一例:

     

    19.8.4 上机实验四:指针的最小移动单位

     

    int arr[6] = {101,102,103,104,105,106};

    int* pI = arr;

     

    cout << "pI 是一个指向整型数组的指针,移动单位:4字节" << endl;

     

    for (int i = 0; i < 6; i++)

       cout << "pI + " << i << " ----> " << pI + i << ", *(pI + i) = "  << *(pI + i) << endl;  

     

    cout << "------------------------------------" << endl;

     

    //接下 来是一个指向char类型数组的指针:

    char str[4] = {'a','b','c','d'}

     

    char*  pC = str;

     

    cout << "pC 是一个指向字符数组的指针,移动单位:1字节" << endl;

    for (int i=0; i < 4; i++)

        cout << "pC + " << i << " ----> " << (int)(pC + i) << ", *(pC + i) = "  << *(pC + i) << endl;  

     

    system("PAUSE");

     

    输出结果:

    (指针的最小移动单位)

    每一行中,程序先输出指针加上偏移量以后的值(地址),比如:1245024、1245028;然后输出偏移后指针指向的值,比如101,102。

    查看移动前后指针存储的地址,我们就可以计算出移动单位。1245028 - 1245024 = 4 (byte)。

     

    现在,我们回头再来看这道题:

     

    有以下代码,设 arr 的地址是  10000010,请问最终 指针变量part2的值是多少?

     

    int arr[] = {1,2,3,4};

    int* parr1 = arr;

    int* parr2;

    int* parr2 = parr + 1;

     

    答案: 10000010 + sizeof (int) = 10000014

     

    这就是对指针加减操作的规则:假设某指针类型为 T* ,则该指针的最小移动单位为: sizeof(T)

    即,若有:

    T* p;

    p + n = p + sizeof(T) * n; 及: p - n = p - sizeof(T) * n;

     

    19.8.5 指针的 += -= 、++、 -- 操作

     

    C、C++ 除了“传统”的 +,- 操作以外,还提供了如题的四种加减操作。这些对于指针同样适用。

     

    int arr[] = {1,2,3,4,5,6,7,8,9,10};

    int* parr1 = arr;

     

    parr1 += 1; //向后称动一个单位

     

    parr1 += 1; 的结果,相当于:  parr1 = parr1 + 2;

    我们再前面的例子是: parr2 = parr1 + 2; 所以计算结果赋值给parr2,所以 parr2 指向了parr1 所指的下一个元素的位置。parr1本身仍然指在第一个元素。

    但对于 parr1 += 1 parr1 = parr1 + 2; 则改变的是 parr1自身的值。

     

    现在,如果来加一句:

     

    parr1 -= 1; //向前移动一个单位

    parr1 又回到 arr 数组的开始位置。

     

    也可以直接移动2个或更多个单位:

     

    parr1 = arr;

    parr1 += 2;  //parr1 现在指向:元素 3

    parr1 -= 2;  //parr1 现在又回到了 元素 1 上面

     

    ++ 和 -- 操作 运算结果等同于 += 1 -= 1

     

    //后置:

    parr1++;

    parr1--;

     

    //前置:

    ++parr1;

    --parr1;

     

    前置与后置的区别,请复习我们第一次讲 ++ 和 --的章节内容。这时仅举一例,用两段代码来对比,请大家思考,并且最好把它写成实际程序运行。

     

    19.8.6 上机实验五:指针的前置++与后置++的区别

     

    //代码片段一:

    int arr[] = {1,2,3,4,5,6,7,8,9,10};

    int* parr1 = arr;

     

    int A = *parr1++;

    int B = *parr1;

     

    cout << "A = " << A << endl;

    cout << "B = " << B << endl;

     

    输出结果:

     

    A = 1;

    B = 2;

     

    代码片段二:

     

    int arr[] = {1,2,3,4,5,6,7,8,9,10};

    int* parr1 = arr;

     

    int A = *++parr1;

    int B = *parr1;

     

    cout << "A = " << A << endl;

    cout << "B = " << B << endl;

     

    输出结果:

     

    A = 2;

    B = 2;

     

     

    19.8.7 * (地址解析符)与 ++ 的优先级

     

    从上例中我们可以看到。当 * (作为地址解析符) ++ 同时作用在指针时,不管是前置还是++,都要比*有更高的优先级。比如代码中的:

     

    int A = *parr++;

     

    我们来一个反证:假设*的优先级比++高,那么,应先计算:

     

    *parr 结果为: 1 (第一个元素)

    然后计算  1++ ,结果为:2。

     

    但实验发现结果为 1,这个1 又是如何来的呢?有点复杂。

    首先,++优先计算,所以应先计算:parr++

    结果是parr指向了下一个元素:2。因为这是后置++,所以,它必须返回自己计算之前的值;所以,在改变parr之前,编译程序会生成一个临时变量,计算原先parr的值。我们假设为 old_parr 。下面是第二步操作:

    A = *old_parr

    由于 old_parr parr 原来的值,指向第一个元素,所以 A 得到值: 1 。

     

    可见,后置 ++ 或 后置-- 操作,需要系统生成一个临时变量。

    如果这个变量占用的内存空间很小(比如指针类型总是只有4字节),则该操作带来的,对程序速度的负面影响可以不计,如果变量很大,并且多次操作。则应在可能的情况下,尽量使用前置++或前置--操作。

     

    你自然会问,前置++就不会产生临时变量吗?我们来试试。

     

    int A = *++parr;

     

    同样,++优先级大于*,所以先计算:++parr

    结果parr 指向下一个元素。因为这是前置++,所以,它只需要返回的,正是自己计算之后的值。下一步是:

    A = *parr;

    由于 parr 此时已完成++操作,指向下一个元素。所以 A 得到值: 2

     

    19.8.8 上机实验六:指针的 ++与--操作

     

    int arr [] = {1,2,3,4,5};

     

    int* parr = arr;

     

    //前进 ++

    for (int i=0; i < 5; i++) //如果为了优化,你可以写成: ++i :)

    {

       cout << *parr << endl;

       parr++;   //如果为了优化,你可以写成:++parr :D

       /*

         上面两句你还可以写成一句: 

         cout << *parr++ << endl;  //这里,你可不能为了优化写成: *++parr.

      */

    }

     

    //后退 --:

    for (int i=0; i < 5; i++)

    {

       parr--;

       cout << *parr << endl;

    }

     

    输出结果:

    (指针的++与--)

     

    19.9 小结

     

    指针是什么?不过也是一个变量,只是存储的是另一个变量的内容地址。

    指针有多大?总是4字节。

     

    如何定义指针? 多了一个*。

    如何为指针赋值?全靠一个个&,除非对方已经是地址(如对方也是指针或是一个数组)。

    如何得到指针所指的变量?如何通过指针改变所指变量?地址解析符:*。

    如何移动指针?加加减减。

    [wangjy17908]
    添加时间:2008-04-11
    版权所有(C)2005-2015