指针与引用

指针与引用

关于指针的两大运算符:

*:称为间接访问或是解除引用运算符。将其运用于指针,可以得到该指针对应的地址处存储的值。

&:称为地址运算符,对一个变量应用地址运算符,就可以获取它的地址。

实际上,由于指针也是一个变量,因此一个指针也可以再取地址,这个地址需存入一个二维指针,不过高维的情形非常复杂,不用担心在考试中遇到。

指针的定义声明

声明一个指针,可以任意指定类型,甚至 * 两边的空格也是任选的,但对每个指针变量名,都需要使用一个*

int *a;
char* b;
double*c;

第一句声明表明: ∗ a *a a类型为 int,由于 * 运算符被用于指针,因此变量 a a a 本身必须为指针.
在口头和书面语表述上,我们说 a 指向 int 类型。

指针定义声明实例

在下面的例子中,假设内存地址从 100 100 100 开始(方便起见,其为十进制数,实际上你在 C++ 程序直接 cout一个地址值,是十六进制的)。

// 内存地址 : |a 100|b 104|c 108|d 112|
int a = 123;
double b = 3.14;
int *c = &a;
double* d = &b;
cout << a << " " << b << " " << c << " " << d << endl;

则最后会输出:
123 3.14 100 104

数组与指针的关系

int a[10];

在上面的声明中,显然 a [ 4 ] a[4] a[4] 是整型( i n t int int)但 a a a 的类型是什么? 它表示的又是什么?

在几乎所有使用数组名的表达式中, 数组名(上面的a)的值是一个指针常量,也就是数组第 1 个元素的地址
在上面的例子中, a 的类型是“指向 int 的常量指针”;如果它是其他类型,那么数组名的类型就是“指向其他类型的常量指针”。

注意这个值是指针常量,而不是指针变量。显然表示完整一段元素的数组的起始位置的指针,是不能轻易改变的——你不能很轻松地移动整个数组。

数组的下标引用表达式

∗(a + i) = a[i]

这两个间接访问与下标引用的表达式是等价的。实际上,写在程序语句中,会有运算优先级上的轻微差异。

int array[10];
int *ap = array + 2;

尝试在以下涉及 ap 的表达式中,写出使用 array的对等表达式:

  • ap:显然, array+2array[2] 符合要求。

  • *ap:间接访问跟随指针访问它所指向的位置,因此答案为 array[2], *(array+2) 也可以。

  • ap[0]:如果你觉得 ap 不是一个数组从而不能这样做,你就陷入了其他编程语言的思维惯性中了。 C++的下标引用和间接访问表达式一样,在这种情况下,对等的表达式是 *(ap+(0)) 0 0 0 和括号可以除去,其结果与前一个表达式相同: array[2]

  • ap+6:如果 ap 指向 array[2],这个加法运算产生的指针所指向的元素是 array[2] 向后移动 6 6 6 个整数位置的元素。对等表达式为 array + 8array[8]

  • *ap+6:小心!这里的两个操作符中,是间接访问先执行!间接访问的结果再与 6 6 6 相加,所以这个表达式相当于表达式 array[2]+6

  • *(ap+6):有了上面的例子,不难想到,这一表达式的值为 array[8]

  • ap:注意,这一表达式是合法、能通过编译的,但其结果与 array 无关。你无法预测编译器会把 ap 放在相对于 array 的什么内存位置。

  • ap[-1]:我们常说的“负数下标会报错”在这里不能直接适用,应该先转换为间接访问表达式:*(array + 2 - 1),从而可知:答案为 array[1]

  • ap[9]:问题在于,原数组 array 只有 10 10 10 个元素,所以会有溢出错误。

  • 2[array]:你也许想不到,这个表达式是合法的,它的值就是 array[2]!因为这里的加法是满足交换律的, a + i = i + a a+i = i+a a+i=i+a

指针的指针

int a = 12, *b = &a, **c = &b;

对上述代码, c c c 的类型显然是一个指针。

b b b 是一个“指向 int 的指针”,则 c c c 是一个指向“指向 int 的指针”的指针。

确切的说,这里的 c c c 是一个指针的指针,这样的定义是合法的,指针的指针同样可以进行间接访问 * 操作。

对于 ***c* 操作符具有从右向左的结合性,因此这个表达式相当于 * (**c)

以下每一行,列出了一个表达式和与之含义相同的表达式。

  • a a a:等价于 12。
  • b b b:等价于 &a。
  • * b b b:等价于 a, 12。
  • c c c:等价于 &b。
  • *** c c c:等价于 *b, a, 12。

注意到之前已经引入了形如 *(a + i) = a[i] 的写法,这里的 a a a 是指向数组第一个元素的指针,是 int*/int[] 类型,而 i i i 是一个位置下标,是 int 类型。

两者不仅可以做加法,还可以做减法,只是对于数组,要注意“加减法”所表示的数组下标移动不要越界。

注意:虽然 C++ 的基础类型在计算机中实际占据的位(bit)不同,但指针的“加减法”所表示的地址在内存中的移动,已经考虑到每次移动的位和指针指向数据类型的位一样了。

long long a[10], *b = a+1; // a[1]
char c[5], *d = c+2; // c[2]

完结撒花~~~

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值