指针的创建,意义与使用

指针的基本概念

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

  • 内存编号是从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 }

运行结果:

 

 

总结:当数组名传入到函数作为参数时,被退化为指向首元素的指针

posted on 2022-07-26 18:03  在野武将  阅读(121)  评论(0)    收藏  举报