指针

1. 指针定义和使用

  • 每一个变量都有一个内存地址,每一个内存地址都定义了可使用连字号(&)运算符访问的地址,它表示了在内存中的一个地址。

  • 指针是一个变量,其值为另一个变量的地址,即内存位置的直接地址。使用指针之前需要先对其声明。指针变量的声明形式为:

    数据类型 *指针名。

示例1:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <iostream>
using namespace std;
int main() {
//1、定义指针,数据类型 *指针名
int a = 10;
int* p;
p = &a;//让指针记录a的地址

//int *p = &a;

cout << "a的地址为:" << &a << endl;
cout << "指针p为:" << p << endl;

//2、使用指针
//可以使用解引用的方式来找到指针所指的数据
*p = 1000;
cout << "a = " << a << endl;
cout << "*p = " << *p << endl;
return 0;
}

运行结果为:

1
2
3
4
a的地址为:0096FC40
指针p为:0096FC40
a = 1000
*p = 1000

示例2:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <iostream>
using namespace std;
int main() {
int* p = (int *)0x1100;//随意指定一个内存地址为0x1100
//将地址0x1100保存在指针p中,即p = 0x1100
//(int *)表示将地址强制转换成int指针类型,这样对p操作时就会以int方式存储
cout << p << endl;

int a = 10;
int* pc = &a;
int* pp = (int *)&a;

cout << "pc = " << hex << pc << endl;
cout << "pp = " << hex << pp << endl;
return 0;
}

运行结果:

1
2
3
00001100
pc = 00DCFE18
pp = 00DCFE18

2. 指针所占内存空间

​ 指针的值是一个代表内存地址的十六进制数,所占空间大小在32位操作系统下,占用四个字节;64位操作系统中占用8个字节。

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <iostream>
using namespace std;
int main() {
int a = 10;
int *p = &a;

cout << "sizeof(p) = " << sizeof(p) << endl;
cout << "sizeof(int *) = " << sizeof(int *) << endl;
cout << "sizeof(float *) = " << sizeof(float *) << endl;
cout << "sizeof(double *) = " << sizeof(double *) << endl;
cout << "sizeof(char *) = " << sizeof(char *) << endl;

return 0;
}

运行结果:

1
2
3
4
5
sizeof(p) = 4
sizeof(int *) = 4
sizeof(float *) = 4
sizeof(double *) = 4
sizeof(char *) = 4

3. 空指针

空指针:指针变量指向内存中编号为0的空间

用途:初始化指针变量

注意:空指针指向的内存不可以访问,0~255之间的内存编号是系统占用的,因此不可以访问。

示例:

1
2
3
4
5
6
7
8
#include <iostream>
using namespace std;
int main() {
int* p = NULL;
cout << p << endl;
//cout << *p << endl;//引发了异常: 读取访问权限冲突。p是nullptr。
return 0;
}

运行结果:

1
00000000

4. 野指针

野指针:指针变量指向非法的内存空间

示例:

1
2
3
4
5
6
7
#include <iostream>
using namespace std;
int main() {
int* p = (int *)0x1100;//随意指定一个内存地址为0x1100
//cout << *p << endl;引发了异常: 读取访问权限冲突。p是0x1100。
return 0;
}

5. const修饰指针

  • 常量指针:const修饰指针

    特点:指针的指向可以修改,但是不可以通过指针来修改它指向的内容。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <iostream>
using namespace std;
int main() {
int a = 10;
int b = 10;
const int* p;
p = &a;
cout << "*p = " << *p << endl;
p = &b;
cout << "*p = " << *p << endl;
//*p = 10;错误,不可以修改常量指针指向的值的内容
a = 20;
cout << "*p = " << *p << endl;
return 0;
}

运行结果:

1
2
3
*p = 10
*p = 10
*p = 10
  • 指针常量:const修饰常量

    特点:指针本身是常量,不可以修改,但是指针指向的值可以修改。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <iostream>
using namespace std;
int main() {
int a = 10;
int b = 20;
//int* const pp;//报错,常量需要设定初始值
int* const p = &a;
//p = &b;//报错,指针是常量,不可以修改
*p = 20;

cout << "*p修改前"<<endl<<"a = " << a << endl;
cout << "*P修改后" << endl;
cout << "*p = " << *p << endl;
cout << "a = " << a << endl;
return 0;
}

运行结果:

1
2
3
4
5
*p修改前
a = 20
*P修改后
*p = 20
a = 20
  • const既修饰指针,又修饰常量

    特点:指针指向的值、指针的指向均不可以改变

1
2
3
4
5
6
7
8
9
10
#include <iostream>
using namespace std;
int main() {
int a = 10;
int b = 20;
const int* const p = &a;
//p = &b;//报错,不可修改
//*p = 10;//报错,不可修改
return 0;
}
  • 记忆技巧

    (1) const = 常量,* = 指针。

    (2) const 紧挨谁,谁不能修改。

    如:const int* p :常量指针,const 紧挨 int*,所以 *p 不可以改。

    ​ int* const p :指针常量,const紧挨 p,所以 p 不可以修改。

6.指针和数组

  • 作用:利用指针访问数组

示例1:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include<iostream>
using namespace std;
int main() {
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
//利用指针访问数组中的元素
//创建int型指针
int* p = arr;//arr是数组的首地址
cout << "数组首地址:" << arr << endl;
cout << "p = " << p << endl;
cout << "arr[0] = " << *p << endl;
p++;//指针向后偏移四个字节
cout << "指针加一后" << endl;
cout << "p = " << p << endl;
cout << "arr[1] = " << *p << endl;

//利用指针遍历数组
p = arr;
for (int i = 0;i < 10;i++) {
cout << *p << " ";
p++;
}
cout << endl;
return 0;
}

运行结果:

1
2
3
4
5
6
7
数组首地址:0057F9C4
p = 0057F9C4
arr[0] = 1
指针加一后
p = 0057F9C8
arr[1] = 2
1 2 3 4 5 6 7 8 9 10

7. 指针和函数

  • 作用:利用指针做函数参数,可以修改实参的值

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include<iostream>
using namespace std;
void Swap(int* a, int* b);
int main() {
int a = 10;
int b = 20;
cout << "交换前:" << endl;
cout << "a = " << a << endl;
cout << "b = " << b << endl;

Swap(&a, &b);//地址传递
cout << "交换后:" << endl;
cout << "a = " << a << endl;
cout << "b = " << b << endl;

return 0;
}
void Swap(int* a, int* b) {
int temp;
temp = *a;
*a = *b;
*b = temp;
}

运行结果:

1
2
3
4
5
6
交换前:
a = 10
b = 20
交换后:
a = 20
b = 10

8.指针、函数、数组案例

  • 封装一个函数,利用冒泡排序,实现对整型数组的升序排序
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
#include <iostream>
using namespace std;
void BubbleSort(int *arr,int len);
int main() {
int arr[10] = { 2,1,4,3,6,5,7,9,8,10 };
int len = sizeof(arr) / sizeof(arr[0]);
BubbleSort(arr, len);
for (int i = 0;i < len;i++) {
cout << arr[i] << " ";
}
cout << endl;
return 0;
}
void BubbleSort(int* arr, int len) {
int* p = arr;
int temp;
for (int i = 0;i < len;i++) {
p = arr;//每趟排序都从头开始
for (int j = 0;j < len - 1 - i;j++) {
//相邻两个元素比较
if (*p > *(p+1)) {
temp = *p;
*p = *(p+1);
*(p+1) = temp;
}
//指针后移
p++;
}
}
}

运行结果:

1
1 2 3 4 5 6 7 8 9 10