接下来我们一起更深层次的了解、学习有关指针的具体内容:
一、指针的指针
我们以下面的这些代码作为开始:
int a = 12;
int *b = &a;
int **c = &b;
表达式**c
的类型是int。让我们对它进行分析,*
操作符具有从右向左的结合性,所以这个表达式相当于*(*c)
,所以我们可以从里向外逐层求值,*c
访问c所指向的位置,我们知道这是变量b。第2个间接访问操作符访问这个位置所指向的地址,也就是变量a。指针的指针并不难懂,如果表达式中出现了间接访问操作符,我们就访问它所指向的位置。接下来我们通过这个表来进一步加深理解:
表达式 | 相当的表达式 |
---|---|
a | 12 |
b | &a |
*b | a,12 |
c | &b |
*c | b,&a |
**c | *b,a,12 |
二、指针表达式
接下来的表达式有些用的很普遍,有些却不常用,接下来让我们一起分析探讨:
char ch = 'a';
char *cp = &ch;
1.ch
当它作为右值使用时,表达式的值为’a’。当这个表达式作为左值使用时,它是这个内存的地址而不是该地址所包含的值。
2.&ch
作为右值,这个表达式的值是变量ch的地址。作为左值使用时非法,原因是当&ch进行求值时,它的结果应该存储于计算机的什么地方,它肯定会存在于某个地方,但无法知道它位于何处。这个表达式并未标识任何机器内存的特定地址。
3.cp
作为右值它表示它就是cp的值,它的左值就是cp所处的内存位置。由于这个表达式并不进行间接访问操作,所以不进行间接访问。
4.&cp
与&ch类似,不过这次所取的是指针变量的地址,它的右值的类型是指向字符的指针的指针。由于存储位置未清晰的定义,所以这个表达式左值非法。
5.*cp
右值为存储于变量ch内部的数据值,即字符a。左值为变量ch的地址。
6.*cp+1
这里有两个操作符,*的优先级高于++,所以首先执行间接访问操作,得到字符a。接下来取得这个值的一份拷贝并把它与1相加,所以表达式的右值为字符b。由于表达式的最终结果的存储位置未清晰定义,所以左值非法。
7.*(cp+1)
在这个表达式中,我们在第6个表达式中增加了一个括号。这个括号使得表达式先执行加法运算,就是把1和变量cp中所存储的地址相加,接下来的间接访问操作访问紧跟ch之后的内存位置。
值得注意的是:间接访问操作符是少数几个其结果作为左值的操作符之一。
8.++cp
++和–操作符在指针中用的相当频繁。在这个表达式中,我们增加了指针变量cp的值。表达式的结果是增值后的指针的一份拷贝,因为前缀++先增加它的操作数的值再返回这个结果。
9.cp++
后缀++操作符同增加cp的值,但它先返回cp值的一份拷贝然后增加cp的值,这样,这个表达式的值就是cp原来值的一份拷贝。
10.*++cp
表达式中间接访问操作作用于增值后的指针的拷贝上,所以它的右值是ch后面那个内存地址的值。
11.*cp++
使用后缀++操作符产生的结果不同,它的右值是变量ch的值,也就是cp原先所指。优先级显示后缀++操作符的优先级高于*操作符,但表达式的结果看上去像是先执行间接访问操作。事实上,这里涉及3个步骤:(1)++操作符产生cp的一份拷贝,(2)然后++操作符增加cp的值,(3)最后,在cp的拷贝上执行间接访问操作。
注意:这个表达式常常在循环中出现,首先用一个数组的地址初始化指针,然后使用这种表达式就可以访问该数组的内容。
12.++*cp
在这个表达式中,由于两个操作符的结合性都是从右至左,所以首先执行的是间接访问操作。然后,cp所指向的位置的值增1,表达式的结果是这个增值后的值的一份拷贝。
13.(*cp)++
使用后缀++操作符,必须加上括号,使得表达式首先执行间接访问操作。这个表达式的计算过程与上一个表达式相似,但它的结果是ch增值前的原先值。
14.++*++cp
这个表达式有三个操作符,结合顺序是从右向左。先前我们已经计算过*++cp
,所以我们只需要增加它的结果值,即给ch后面那个内存地址的值再进行++操作,最终结果就是那个位置的值再加1。
15.++*cp++
这个表达式和前一个表达式的区别在于这次第1个++操作符是后缀形式而不是前缀形式,由于它的优先级较高,所以先执行它。间接访问操作符所访问的是cp所指向的位置而不是cp所指向位置后面的那个位置。
以上就是我今天简要介绍的指针表达式,后续我将继续分享指针的简单使用实例!!!!!