野指针我老熟人了。。。。
基本概念 {#基本概念}
作用: 通过指针间接访问内存
- 内存编号是从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修饰指针 {#const修饰指针}
在C++中,当使用const
修饰指针时,它有两种不同的含义,这取决于const
的位置:
-
const
位于星号(*)之前 :这表示指针指向的内容是常量,即不能通过这个指针修改所指向的数据。但指针本身可以改变,指向不同的地址。|-------------------|--------------------------------------------------------------------------------------------------------------------------------------------------| |
1 2 3 4 5
|int x = 10; int y = 20; const int* p = &x; // p是指向int常量的指针 p = &y; // 正确:可以改变p指向的地址 *p = 30; // 错误:不能通过p修改所指向的数据
| -
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++中,当你将数组作为参数传递给函数时,它实际上被转换为一个指向数组首元素的指针。这意味着在函数内部,你没有数组的大小信息。因此,在函数内部无法直接计算数组的长度。