【C++学习】指针
Published in:2024-08-10 | category: C++
Words: 1.4k | Reading time: 6min | reading:

野指针我老熟人了。。。。

基本概念

作用: 通过指针间接访问内存

  • 内存编号是从0开始记录的,一般用十六进制数字表示
  • 可以利用指针变量保存地址

指针变量的定义和使用

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

int main(){

//1.指针的定义
int a=10;
int * p;

p=&a;
cout<<&a<<endl;
cout<<p<<endl;

//2.指针的使用
//通过*操作指针变量指向的内存
cout<<"*p = "<<*p<<endl;

system("pause");

return 0;

}

指针变量和普通变量的区别

  • 普通变量存放的是数据,指针变量存放的是地址
  • 指针变量可以通过”*”操作符,操作指针变量指向的内存空间,这个过程称为解引用

用&获取变量的地址

指针所占内存空间

Q: 指针也是种数据类型,那么这种数据类型占用多少空间呢?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
int main() {

int a = 10;

int * p;
p = &a; //指针指向数据a的地址

cout << *p << endl; //* 解引用
cout << sizeof(p) << endl;
cout << sizeof(char *) << endl;
cout << sizeof(float *) << endl;
cout << sizeof(double *) << endl;

system("pause");

return 0;
}

在C++中,指针类型的大小取决于所运行的系统架构。通常情况下:

  • 在32位系统中,指针通常占用4个字节。
  • 在64位系统中,指针通常占用8个字节。

空指针和野指针

空指针

1
2
3
4
5
6
7
8
9
10
11
12
13
int main() {

//指针变量p指向内存地址编号为0的空间
int * p = NULL;

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

system("pause");

return 0;
}

野指针

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

1
2
3
4
5
6
7
8
9
10
11
12
int main() {

//指针变量p指向内存地址编号为0x1100的空间
int * p = (int *)0x1100;

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

system("pause");

return 0;
}

在编写C++程序时,应确保指针指向有效的内存地址。直接将指针指向一个硬编码的地址,而没有确保该地址是有效和安全的,是一种危险的做法。正确的做法是使用动态内存分配(如new关键字)来获取内存,或者确保指针指向已分配的内存区域。

空指针和野指针都不是我们申请的空间,因此不要访问

const修饰指针

在C++中,当使用const修饰指针时,它有两种不同的含义,这取决于const的位置:

  1. const位于星号(*)之前:这表示指针指向的内容是常量,即不能通过这个指针修改所指向的数据。但指针本身可以改变,指向不同的地址。
    1
    2
    3
    4
    5
    int x = 10;
    int y = 20;
    const int* p = &x; // p是指向int常量的指针
    p = &y; // 正确:可以改变p指向的地址
    *p = 30; // 错误:不能通过p修改所指向的数据
  2. const位于星号(*)之后:这表示指针本身是常量,即不能更改指针的值(它所指向的地址)。但可以通过指针修改它所指向的数据。
    1
    2
    3
    4
    5
    int x = 10;
    int y = 20;
    int* const p = &x; // p是常量指针
    *p = 30; // 正确:可以通过p修改所指向的数据
    p = &y; // 错误:不能更改p的值(它所指向的地址)

指针和数组

利用指针访问数组中元素

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
int main() {

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

int* p = a;
cout << "第一个元素:" << a[0] << endl;
cout << "指针访问第一个元素:" << *p << endl;

for (int i = 0; i < 10; i++) {

cout << *p << endl;
p++;

}

system("pause");

return 0;
}

指针和函数

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

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
//值传递
void swap1(int a ,int b)
{
int temp = a;
a = b;
b = temp;
}
//地址传递
void swap2(int * p1, int *p2)
{
int temp = *p1;
*p1 = *p2;
*p2 = temp;
}

int main() {

int a = 10;
int b = 20;
swap1(a, b); // 值传递不会改变实参

swap2(&a, &b); //地址传递会改变实参

cout << "a = " << a << endl;

cout << "b = " << b << endl;

system("pause");

return 0;
}

指针、数组、函数

封装一个函数: 利用冒泡排序,实现对整型数组的升序排序
例如数组:int arr[10]={4,3,6,9,1,2,10,8,7,5};

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
//冒泡排序函数
void bubbleSort(int * arr, int len) //int * arr 也可以写为int arr[]
{
for (int i = 0; i < len - 1; i++)
{
for (int j = 0; j < len - 1 - i; j++)
{
if (arr[j] > arr[j + 1])
{
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
}

//打印数组函数
void printArray(int arr[], int len)
{
for (int i = 0; i < len; i++)
{
cout << arr[i] << endl;
}
}

int main() {

int arr[10] = { 4,3,6,9,1,2,10,8,7,5 };
int len = sizeof(arr) / sizeof(int);

bubbleSort(arr, len);

printArray(arr, len);

system("pause");

return 0;
}

当数组名传入到函数作为参数时,被退化为指向首元素的指针
在C++中,当你将数组作为参数传递给函数时,它实际上被转换为一个指向数组首元素的指针。这意味着在函数内部,你没有数组的大小信息。因此,在函数内部无法直接计算数组的长度。

Prev:
【C++学习】结构体
Next:
【C++学习】函数