C++指针

2

C++指针

  指针是C/C++最精髓的内容,也是大多数程序员幼崽的童年阴影,噩梦的开始。当然也包括本菜鸟也深受其害,在这里我们不说的很详尽,因为我也是个freshman,这个博客的内容是普及一下指针的基本用法,至于复杂的情况,可以参考上面的三本宝典,都是C/C++程序员走上不归路的必读书籍。

指针定义

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include<iostream>
using namespace std;

int main() {

//指针和普通变量的定义一样,可以定义时初始化,也可以在使用时初始化。指针的意思是指向某一块内存空间,因此其代表的一个地址,前面加上*代表取出地址指向的值。
int a = 10;
int* p = &a;
int* p1;
p1 = &a;

//可以看出p等价于&a,在数组中已经介绍了取地址符&,因此p指代的是a的地址,*p则指代地址中存放的值。
cout << "p = " << p << endl;
cout << "*p = " << *p << endl;
cout << "&a = " << &a << endl;
cout << "a = " << a << endl;

int b = a;
b += 2;

//int b = a,说明创建一个变量,让其值等于a,但是b和a是两个不同的变量,因此b的变化和a无关,所以b += 2时,a仍保持不变。
cout << "b = " << b << endl;
cout << "a = " << a << endl;

*p += 2;

//*p += 2,说明让p指向的内存空间中的值加2,但是p指向的内存空间就是a,相当于a的门牌号,因此*p += 2就等价于a += 2,所以a的值发生了变化。
cout << "p = " << p << endl;
cout << "*p = " << *p << endl;
cout << "&a = " << &a << endl;
cout << "a = " << a << endl;

return 0;
}

1

const与指针

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#include <iostream>
using namespace std;

int main() {

int a = 10;
int b = 20;

//const修饰指针,称为常量指针,const修饰*p,说明指针指向的值是不可以改变的,但是可以改变指针的指向。
const int* p1 = &a;

cout << "a = " << a << endl;
cout << "&a = " << &a << endl;
cout << "b = " << b << endl;
cout << "&b = " << &b << endl;
cout << "p1 = " << p1 << endl;
cout << "*p1 = " << *p1 << endl;

p1 = &b;

//p1指向了b,因此a的值没有变,p1为b的地址,p1指向的值为b的值
cout << "a = " << a << endl;
cout << "&a = " << &a << endl;
cout << "b = " << b << endl;
cout << "&b = " << &b << endl;
cout << "p1 = " << p1 << endl;
cout << "*p1 = " << *p1 << endl;

int c = 30;
int d = 40;

//const修饰常量,称为指针常量,const修饰p,说明指针的指向是不可以改变的,但是可以改变指针指向的值。
int* const p2 = &c;

cout << "c = " << c << endl;
cout << "d = " << d << endl;
cout << "&c = " << &c << endl;
cout << "&d = " << &d << endl;
cout << "p2 = " << p2 << endl;
cout << "*p2 = " << *p2 << endl;

*p2 = d;

//p2为c的地址,现在将地址指向的值改为d,因此c变为d的值,p2的地址没有改变
cout << "c = " << c << endl;
cout << "d = " << d << endl;
cout << "&c = " << &c << endl;
cout << "&d = " << &d << endl;
cout << "p2 = " << p2 << endl;
cout << "*p2 = " << *p2 << endl;

return 0;
}

2

指针和数组

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
#include<iostream>
using namespace std;

int main() {

int a[3] = { 1, 2, 3 };

//在数组章节中说过,一维数组名就是数组的首地址,因此可以将一位数组名赋值给指针
int* p = a;

//访问元素时,可以通过指针的方式,p++代表指针向后移动一个单位,指针移动的单位根据指针类型确定,指针是什么类型则移动相应的大小。
//这里指针为int类型,因此p++就相当于指针从数组第一个元素移动到第二个元素,因为数组也是按照内存大小存放的。
for (int i = 0; i < 3; i++) {

cout << *p++ << " ";
}
cout << endl;

p = a;
//还可以通过类似数组的方式,通过指针索引访问数组元素。
for (int i = 0; i < 3; i++) {

cout << p[i] << " ";
}
cout << endl;

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

//指向指针的指针,很好理解,指针p1是二维数组中第一行的首地址,虽然二维数组名也是一个地址,但是不能通过赋值操作直接给指针赋值。
//指针p2是指针p1的地址,因此p2指向p1,p1指向第一行的首地址,所以*p2就是p1的值,**p2就是b[0][0]的值
int* p1 = b[0];
int** p2 = &p1;

for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
//注意这里的写法是有讲究的,p2指向p1,因此在一维数组中p1++就等价于(*p2)++。
//不能写成*p2++,*p2++指的是p2指针自加1,p2指针自加是没有意义的。
cout << *(*p2)++ << " ";
}
cout << endl;
}

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

//指针数组,p3的每一个元素都是一个指针,分别指向数组c每一行的首地址,指针p4指向指针数组的首地址。
int* p3[3] = { c[0], c[1], c[2] };
int** p4 = p3;

for (int i = 0; i < 3; i++, p4++) {
for (int j = 0; j < 3; j++) {
//p4是指针数组的首地址,*p4指的是p3[0]的值,而p3[0]又是数组c[0][0]的地址
//因此*(*p4)是c[0][0]的值,做完之后(*p4)自增1,等价于p3[0]指向了c[0][1]。
//注意在第一层循环中包含着p4++这个操作,当p3[0]指向c[0][2]以后,p4指向指针数组的下一个元素p3[1],然后开始读取c数组第二行的元素。
//如果将p4++删去,仍可以得到相同的答案,如何理解呢?因为二维数组也是按照顺序存放的,因此指针p3[0]读取到第一行最后一个元素后,自增时也会指向第二行的第一个元素,因此也是正确的。
cout << *(*p4)++ << " ";
}
cout << endl;
}

return 0;
}

4

值传递

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#include<iostream>
using namespace std;

//swap参数列表中的变量为普通变量
void swap(int a, int b) {

cout << "a = " << a << endl;
cout << "b = " << b << endl;
cout << "&a = " << &a << endl;
cout << "&b = " << &b << endl;
cout << endl;

int temp = a;
a = b;
b = temp;

cout << "a = " << a << endl;
cout << "b = " << b << endl;
cout << "&a = " << &a << endl;
cout << "&b = " << &b << endl;
cout << endl;
}

int main() {

int a = 10;
int b = 20;

cout << "a = " << a << endl;
cout << "b = " << b << endl;
cout << "&a = " << &a << endl;
cout << "&b = " << &b << endl;
cout << endl;

//当调用函数时,传入变量值,则会将实参值拷贝到形参中去,因此形参会获得实参的值,但是它们的地址是不同的。
//所以进行交换时,两个形参的值进行了交换,在调用结束后,形参的作用域结束,被销毁,并不会影响到实参的值。
swap(a, b);

cout << "a = " << a << endl;
cout << "b = " << b << endl;
cout << "&a = " << &a << endl;
cout << "&b = " << &b << endl;

return 0;
}

4

址传递

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#include<iostream>
using namespace std;

//swap参数列表中的变量为指针变量
void swap(int* a, int* b) {

cout << "*a = " << *a << endl;
cout << "*b = " << *b << endl;
cout << "a = " << a << endl;
cout << "b = " << b << endl;
cout << endl;

int temp = *a;
*a = *b;
*b = temp;

cout << "*a = " << *a << endl;
cout << "*b = " << *b << endl;
cout << "a = " << a << endl;
cout << "b = " << b << endl;
cout << endl;
}

int main() {

int a = 10;
int b = 20;

cout << "a = " << a << endl;
cout << "b = " << b << endl;
cout << "&a = " << &a << endl;
cout << "&b = " << &b << endl;
cout << endl;

//当调用函数时,传入地址值,则会将实参地址值拷贝到形参中去,因此形参会获得实参的地址值。
//所以进行交换时,两个地址的指向的内容进行了交换,在调用结束后,形参的作用域结束,被销毁,但是地址指向的内容已经发生了改变,所以实参会发生变化。
swap(&a, &b);

cout << "a = " << a << endl;
cout << "b = " << b << endl;
cout << "&a = " << &a << endl;
cout << "&b = " << &b << endl;

return 0;
}

4

C++小结

  指针是C/C++中最具有魅力的地方,其实所有的高级语言都有指针,只不过将其包装了起来,让使用者感觉不到在操作指针,最简单的例子,Java中的this,和Python中的self,其本质都是一个指针,学好了指针可以让我们更加了解语言背后的动作,因此小伙伴们要克服恐惧,奥里给!

-------------本文结束感谢您的阅读-------------
0%