C++ 基础知识(5)--指针

变量的内存地址

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <iostream>

using namespace std;

int main ()
{
int num;
bool boolValue;
char strArray[1];
char charValue;
char caherValue1 = 'a';

cout << &num << endl;
cout << &boolValue << endl;
cout << &strArray << endl;
cout << &charValue << endl;
cout << &caherValue1 << endl;

return 0;
}

运行结果:

1
2
3
4
5
0x16fdff238
0x16fdff237
0x16fdff236

a

可以发现当为char类型的时候是没有内存地址的,即使赋值了也只是显示赋值的内容,char数组是有内存地址的。

什么是指针?

指针的作用是指向内存地址,指针是一个变量。指针的声明方式为type *name,中文理解方式是数据类型 指针的名字。例子:

1
2
3
4
int    *ip;    /* 一个整型的指针 */
double *dp; /* 一个 double 型的指针 */
float *fp; /* 一个浮点型的指针 */
char *ch /* 一个字符型的指针 */

什么是空指针?

定义:指针变量指向内存中编号为0的空间。
用途:用来初始化指针
注意:空指针指向的内存不可访问

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <iostream>

using namespace std;

int main ()
{
// 指针变量指向内存中编号为0的空间
int * p = NULL;

cout << p << endl; // 0x0

// 内存编号为0~255为系统占用内存,不允许用户访问
cout << *p << endl; // 报错

return 0;
}

什么是野指针?
定义: 指针变量指向的是非法的内存编号

比如 0x1100 内存编号并不存在,指针指向该地址就属于指向了非法的内存编号。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <iostream>

using namespace std;

int main ()
{
int * p = (int *)0x1100;

cout << p << endl; // 0x1100

// 访问野指针报错
cout << *p << endl;

return 0;
}

指针的用法

  1. 声明一个指针变量
  2. 将一个变量的内存地址赋值给指针
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 ()
{
int num = 10;
int * p = &num;
cout << *p << endl;

bool boolValue = false;
bool * p1 = &boolValue;
cout << *p1 << endl;

char charValue = 'a';
char * p2 = &charValue;
cout << *p2 << endl;

return 0;
}

运行结果:

1
2
3
10
0
a

*p是值,p是内存地址

const修饰指针

const 修饰指针有三种情况:

  1. const修饰指针 — 常量指针
  2. const修饰常量 — 指针常量
  3. const即修饰指针,又修饰常量

常量指针: 指针的指向可以改变,但指针指向的值不能更改。

错误例子:

1
2
3
4
5
int num = 10;
int num1 = 20;
const int * p = &num;
*p = 20; // 报错
cout << *p << endl;

正确例子:

1
2
3
4
5
int num = 10;
int num1 = 20;
const int * p = &num;
p = &num1;
cout << *p << endl; // 20

指针常量:指针的指向不可以改变,指针的指向的值可以更改。

错误例子:

1
2
3
4
5
int num = 10;
int num1 = 20;
int * const p = &num;
p = &num1; // 报错
cout << *p << endl;

正确例子:

1
2
3
4
5
int num = 10;
int num1 = 20;
int * const p = &num;
*p =30;
cout << *p << endl; // 30

const修饰指针和常量: 指针的指向和指向的值都不可以更改。

错误例子:

1
2
3
4
5
6
int num = 10;
int num1 = 20;
const int * const p = &num;
p = &num1; // 报错
*p = 30; // 报错
cout << *p << endl;

正确例子:

1
2
3
4
int num = 10;
int num1 = 20;
const int * const p = &num;
cout << *p << endl; // 10

指针和数组

当数组赋值给指针时,指针指向的是数组第一位的内存地址。可以通过 ++,改变指针的指向。

1
2
3
4
5
6
int numArray[4] = {1,2,3,4};
int * p = numArray;
cout << * p << endl; // 1

p++;
cout << * p << endl; // 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
#include <iostream>

using namespace std;

// 未使用指针的函数
void test(int a, int b){
int temp = b;
b = a;
a = temp;
};

// 使用指针的函数
void test1(int * a, int * b){
int temp = * b;
* b = * a;
* a = temp;
}

int main(){
int a = 10;
int b = 20;
test(a, b);
cout << a << endl; // 10
cout << b << endl; // 20

test1(&a, &b);
cout << a << endl; // 20
cout << b << endl; // 10

return 0;
}

一旦使用指针作为形参接收值,指针修改指向的值,就会导致该内存地址的值改变。