指针的创建,意义与使用
指针的基本概念
指针的作用: 可以通过指针间接访问内存
-
内存编号是从0开始记录的,一般用十六进制数字表示
-
可以利用指针变量保存地址
指针变量的定义和使用
指针变量定义语法: 数据类型 * 变量名;
*修饰变量时 *叫做指针,变量叫做指针变量
1 #include <iostream> 2 using namespace std; 3 int main() 4 { 5 int a = 10; 6 cout << "a初始值为 :" << a << endl; 7 int* p;//*加变量名代表着这个是一个指针变量 8 p = &a;//&加变量名意味着这个变量的地址,这里我们将a的地址赋值给了p,当然我们也可以在创建指针变量p的时候赋值:int* p = a; 9 cout << "a 地址 :" << &a << endl; 10 cout << "p的值 : " << p << endl;//这里两个的输出值是一样的因为我们已经把&a 赋值给了 p 11 *p = 20; 12 /*因为p通过定义是指针函数,然后又将a的地址赋值给了p,所以p相当于一个找到a的地图, 13 因此我们可以通过*引用p中的地址指向a的值,也就是说*通过p地图找到了a地的宝藏, 14 所以当*拿着地图p时,a地的宝藏也可以说是*的宝藏,*p可以控制a地宝藏的数量 */ 15 cout << " a 现在等于 :" << a << endl; 16 cout << "a 现在地址 :" << &a << endl;//不会因为值改变而改变 17 cout << " *p 指向 :" << *p << endl; 18 cout << "p的地址为 :" << &p << endl;//p虽然承担着地图的功能,但因为它储存了a的地址,所以它本身也有地址 19 return 0; 20 }

指针内存:
1 #include <iostream> 2 using namespace std; 3 int main() { 4 5 int a = 10; 6 7 int* p; 8 p = &a; //指针指向数据a的地址 9 10 cout << *p << endl; //* 解引用 11 cout << sizeof(p) << endl;//等同于sizeof(int *) 12 cout << sizeof(char*) << endl; 13 cout << sizeof(float*) << endl; 14 cout << sizeof(double*) << endl; 15 /* 16 所有指针类型在32位(x86)操作系统下是4个字节,所有指针类型在64位(x64)操作系统下是4个字节 17 */ 18 19 system("pause"); 20 21 return 0; 22 }

空指针 :
1 int main() { 2 3 //指针变量p指向内存地址编号为0的空间 4 int * p = NULL;//可以用0也是一个意思 5 6 //语法上不会报错,但是运行时会报错.因为空指针不可访问 7 //内存编号0 ~255为系统占用内存,不允许用户访问 8 cout << *p << endl; 9 10 system("pause"); 11 12 return 0; 13 }


野指针 :指针变量指向非法的内存空间(没有定义的)
1 int main() { 2 3 //指针变量p指向内存地址编号为0x1100的空间 4 int * p = (int *)0x1100; 5 6 //访问野指针报错 7 cout << *p << endl; 8 9 system("pause"); 10 11 return 0; 12 }
const修饰
const 既修饰指针又修饰变量:
1 int main() { 2 3 int a = 10; 4 int b = 20; 5 const int * const p = &a; 6 cout << *p << endl; 7 //*p = 20;//error 8 //*p = &b;//error 9 cout << *p << endl; 10 return 0; 11 }
const修饰指针 :常量指针
1 #include <iostream> 2 using namespace std; 3 int main() { 4 int a = 10; 5 int b = 20; 6 const int* p = &a; 7 cout << p << endl; 8 //*p = 20;//error 9 p = &b; 10 cout << p << endl; 11 return 0; 12 }

const修饰常量 :指针常量
1 #include <iostream> 2 using namespace std; 3 int main() { 4 int a = 10; 5 int b = 20; 6 int* const p = &a; 7 cout << *p << endl; 8 *p = 20; 9 //p = &b;//error 10 cout <<* p << endl; 11 return 0; 12 }

技巧:看const(常量)右侧紧跟着的是指针还是常量, 是指针就是常量指针,是常量就是指针常量,紧跟着谁谁就可以改变,但同时跟着两个就两个都不能改变。
const的本质是不允许指针来改变被指地址的某个部分,
比如指针常量是不允许通过修改指针来修改被指向变量的值,但是被指向的变量可以自己修改值,此时指针解引用后的值是修改后的值;
比如常量指针是不允许修改指针的指向变量的值,而不代表指针解引用后值永远会是第一个指向变量的值,当指针修改指向地址后,解引用的值就会变成新地址变量的值
如下:

指针和数组
1 #include <iostream> 2 using namespace std; 3 int main() { 4 int arr[] = { 1,2,3,4,5,6,7,8,9,10 }; 5 int* p = arr; //指向数组的指针,数组名就是数组的首地址 6 cout << "第一个元素: " << arr[0] << endl; 7 cout << "指针访问第一个元素: " << *p << endl;//数组地址和第一个元素地址一样 8 for (int i = 1; i <= sizeof(arr) / sizeof(arr[0]); i++) 9 { 10 cout << "数组第" << i << "个数字为" << *p << endl; 11 p++;//因为指针类型与数组一样,所以指针每偏移一次,解引用时对应数组元素加一或减一,这里是让P往增加四个字节,也就是让p指向arr的地址往右偏移四个字节 12 } 13 return 0; 14 }
指针与函数
**作用:**利用指针作函数参数,可以修改实参的值
1 #include <iostream> 2 using namespace std; 3 //值传递 4 void swap1(int a ,int b) 5 { 6 int temp = a; 7 a = b; 8 b = temp; 9 } 10 //地址传递 11 void swap2(int * p1, int *p2) 12 { 13 int temp = *p1; 14 *p1 = *p2; 15 *p2 = temp; 16 } 17 18 int main() { 19 20 int a = 10; 21 int b = 20; 22 swap1(a, b); // 值传递不会改变实参 23 24 swap2(&a, &b); //地址传递会改变实参, 25 //因为是赋给形参实参的地址值 ,所以当作指针函数来看,可以改变实参的值 26 27 cout << "a = " << a << endl; 28 29 cout << "b = " << b << endl; 30 31 system("pause"); 32 33 return 0; 34 }

总结:如果不想修改实参,就用值传递,如果想修改实参,就用地址传递
指针配合数组函数的案例 :
**案例描述:**封装一个函数,利用冒泡排序,实现对整型数组的升序排序
例如数组:int arr[10] = { 4,3,6,9,1,2,10,8,7,5 };
1 //冒泡排序函数 2 void bubbleSort(int * arr, int len) //int * arr 也可以写为int arr[] 3 { 4 for (int i = 0; i < len - 1; i++) 5 { 6 for (int j = 0; j < len - 1 - i; j++) 7 { 8 if (arr[j] > arr[j + 1]) 9 { 10 int temp = arr[j]; 11 arr[j] = arr[j + 1]; 12 arr[j + 1] = temp; 13 } 14 } 15 } 16 } 17 18 //打印数组函数 19 void printArray(int arr[], int len) 20 { 21 for (int i = 0; i < len; i++) 22 { 23 cout << arr[i] << endl; 24 } 25 } 26 27 int main() { 28 29 int arr[10] = { 4,3,6,9,1,2,10,8,7,5 }; 30 int len = sizeof(arr) / sizeof(int); 31 32 bubbleSort(arr, len); 33 34 printArray(arr, len); 35 36 system("pause"); 37 38 return 0; 39 }
分文件编写版:
头文件:
1 #include <iostream> 2 using namespace std; 3 void bob(int* arr, int line); 4 void pri(int* arr, int lint);
源文件 :
1 #include "标头.h" 2 void bob(int* arr, int lint ) //int * arr 也可以写为int arr[] 3 { 4 for (int n = 0; n <= lint; n++) 5 { 6 for (int i = 0; i < lint - n; i++) 7 { 8 if (arr[i] > arr[i + 1]) 9 { 10 int temp = arr[i]; 11 arr[i] = arr[i + 1]; 12 arr[i + 1] = temp; 13 } 14 } 15 } 16 } 17 void pri(int* arr, int lint) //int * arr 也可以写为int arr[] 18 { 19 for (int j = 0; j <= lint; j++) 20 { 21 cout << arr[j] << " "; 22 } 23 }
程序文件 :
1 #include <iostream> 2 #include "标头.h" 3 using namespace std; 4 int main() 5 { 6 int arr[10] = { 4,3,6,9,1,2,10,8,7,5 }; 7 int line = sizeof(arr) / sizeof(arr[0]) - 1; 8 bob(arr, line); 9 pri(arr, line); 10 return 0; 11 }
运行结果:

总结:当数组名传入到函数作为参数时,被退化为指向首元素的指针
浙公网安备 33010602011771号