欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

C++学习(二十三)(C语言部分)之 指针4

程序员文章站 2022-06-26 10:01:37
指针 指针 存放地址 只能存放地址 使用 &取地址运算符 *取值 解引用运算符 malloc 申请堆内存 free释放堆内存 1.1 指针 存放的地址(变量地址 常量区的地址 堆区内存首地址 数组首地址 指针变量的地址 函数地址) 1.指针 也是变量 指针也有类型 int *p; //定义的时候 去 ......

指针
指针 存放地址 只能存放地址
使用
&取地址运算符 *取值 解引用运算符
malloc 申请堆内存 free释放堆内存


1.1 指针 存放的地址(变量地址 常量区的地址 堆区内存首地址 数组首地址 指针变量的地址 函数地址)
1.指针 也是变量 指针也有类型
int *p; //定义的时候 去掉变量名 剩下的就是类型
int * 类型

存放什么类型的变量地址 int (去掉*p之后 剩下的就是存放的地址中变量的类型)

二级指针
int **pp;
pp的类型 int**
pp指向的数据类型 存放int*类型的 变量地址

int(*)[5];//数组指针
int(*)[5]//指针l类型
int[5] //指向的数组的地址

定义是定义 使用是使用 是分开的
parr[i][j] *(*(parr+i)+j) 使用的时候这是等价的 但定义的时候不一样

重点
1.指针类型
2.指针指向数据的类型
3.指针指向什么数据

1.2 指针加减
1.指针+int 指针-int类型
p+1 让指针指向下一个元素
2.p++ p--
3.指针和指针相减 的道到的值距离

//指针相加、相乘、相除 没有意义

如果不清楚指针移动之后 指向什么区域 就不要对指针++或者--
特别是申请内存的时候(不要随便移动这个指向堆内存首地址的指针)

*(p+i) p[i] 两个内部实现是一样的


1.3 常用的指针
1.指针常量
2.常量指针

3.指针数组
4.数组指针

5.指针函数
6.函数指针


xx指针 xx是修饰 常量指针 是指:指向常量的指针

指针xx 指针是修饰 指针常量 是指:类型是指针的常量
指针函数 函数类型(返回值类型)是指针的函数


指针常量
int *const p; //*表示指针 const表示常量

定义的时候是什么类型就一直是什么类型

指针数组+二维数组 (都需要解引用两次 但是不一样)
数组指针 可以指向二维数组 怎么定义数组指针 怎么赋值
用法 正确赋值之后 和二维数组是一样的
一行有多少个元素 存的什么类型的元素

 

C++学习(二十三)(C语言部分)之 指针4

 

C++学习(二十三)(C语言部分)之 指针4

 

代码笔记:

  1 #include<stdio.h>
  2 #include<stdlib.h>
  3 /*--01
  4 int max(int a, int b)
  5 {
  6     return a > b;//返回比较的结果 1或者0
  7 }
  8 
  9 int fun(int x, int y, int z,int(*pmax)(int,int))//最后一个参数 函数指针 (形参函数指针)
 10 {
 11     return pmax(x, y);//用函数指针调用函数
 12 }
 13 */
 14 
 15 //排序  冒泡 选择 插入 桶排序 快速 希尔 堆排序 归并排序
 16 
 17 //冒泡排序   思路 循环比较相邻的元素 大小关系和排序方向不和 交换两个元素  
 18 //从小到大排序  从左到右开始比较 如果第一个比第二个小 顺序不变 始终保持 左边小又变大
 19 //每轮可以使得一个数字沉底  n个元素 只要循环n-1轮
 20 
 21 int max(int a, int b)
 22 {
 23     return a > b;
 24 }
 25 int min(int a, int b)
 26 {
 27     return a < b;
 28 }
 29 
 30 #if 0
 31 void bull_sort(int arr[],int n)  //冒牌排序 arr是存放数据的数组 n是数组中元素个数
 32 {
 33     int temp;//中间变量
 34     for (int i = 0; i < n - 1; ++i)  //循环n-1轮 每轮沉底一个数字 控制循环次数
 35     {
 36         //排序过程
 37         for (int j = 0; j < n-1; ++j)  //j<n&&j+1<n   防止越界  控制循环
 38         {
 39             if (arr[j] > arr[j + 1])  //从小到大排序 前面元素比后面元素大 交换
 40             {//从大到小的排序 前面的元素比后面的元素小 交换
 41                 temp = arr[j];
 42                 arr[j] = arr[j+1];
 43                 arr[j+1] = temp;//temp中间变量 用来交换
 44             }
 45         }
 46         printf("第[%d]轮排序:", i);//第i轮排序
 47         for (int k = 0; k < 10; ++k)
 48         {
 49             printf("%d\t", arr[k]);
 50         }
 51         printf("\n\n");
 52     }
 53 }
 54 #endif
 55 
 56 //优化后的代码 运用函数指针
 57 void bull_sort(int arr[], int n, int(*p)(int,int))  //函数指针 用来控制从小到大还是从大到小 冒牌排序 arr是存放数据的数组 n是数组中元素个数
 58 {
 59     int temp;//中间变量
 60     for (int i = 0; i < n - 1; ++i)  //循环n-1轮 每轮沉底一个数字 控制循环次数
 61     {
 62         //排序过程
 63         //for (int j = 0; j < n-1; ++j)  //j<n&&j+1<n   防止越界  控制循环
 64         for (int j = 0; j<n - 1-i;++j)//优化之后的算法 j<n - 1-i  可以减少比较次数
 65         {
 66             if (p(arr[j],arr[j + 1]))  //从小到大排序 前面元素比后面元素大 交换
 67             {//从大到小的排序 前面的元素比后面的元素小 交换
 68                 temp = arr[j];
 69                 arr[j] = arr[j+1];
 70                 arr[j+1] = temp;//temp中间变量 用来交换
 71             }
 72         }
 73         printf("第[%d]轮排序:", i);//第i轮排序
 74         for (int k = 0; k < 10; ++k)
 75         {
 76             printf("%d\t", arr[k]);
 77         }
 78         printf("\n\n");
 79     }
 80 }
 81 int main()
 82 {
 83 #if 0
 84     double x;
 85     int *p = &x;//如果定义一个double型的x 那么赋值给int*型p 就会报错    
 86     //int* 是指针的类型
 87     
 88     int(*parr)[5] = &x;//这是一个数组指针类型 与定义的double型的是不相附的 所以会报错
 89     
 90     //可以如下方式定义
 91     int arr[5];
 92     int(*parr)[5] = &arr;//取一位数组的地址
 93     //使用如下
 94     (*parr)[0];//arr[0]的地址  parr相当于&arr地址  --->*parr 相当于arr  arr[0] 相当于 (*parr)[0]
 95     //取变量地址 不会取数组地址--->很麻烦
 96 #endif
 97 
 98 #if 0
 99     //常用的方式
100     int *p;
101     p = arr;//常规定义方法 保存的是数组首元素的地址
102     *p = 1;//相当于arr[0]=1;
103     p += 4;//指针加减法是地址的加减 指针加一 地址加多少 要看指针指向变量的类型而定  指向下一个元素的地址 不是下标  指针加减之后还是指针
104 #endif
105 
106 #if 0
107     p = (int*)malloc(sizeof(int)* 10);//申请内存
108     p++;//p++之后不再指向原来的地址
109     free(p);//释放内存     运行后会报出一个错误 出现一个断点
110 #endif
111 
112 #if 0
113     int x;//const 常属性 不能修改
114     int *const p=&x; //指针常量 *表示指针  const表示常量 定义的时候必须赋值
115     //const修饰的p  p不可以修改 *p可以修改
116 
117     *p = 2;//赋值  scanf也可以赋值
118     p++;//不能修改指向
119     scanf("%d", p);//scanf要用地址 用指针也可以
120 
121 
122     int const*q;//*在const后面 常量指针(指向常量 不能修改常量)
123     //*q不能修改 q可以修改 *q不能作为左值 q没有修改内容的权限
124     
125     q = &x;
126     *q = 23;//不能修改内容   *q不能作为左值
127 #endif
128 
129 #if 0
130     //指针数组 数组
131     //类型 数组名[数组大小]
132     int* arr[10];//指针数组  表示数组中存放的是int*类型的变量
133     //存放指针的数组
134     //总共10个int*
135 
136     //数组指针
137     int(*parr)[10];//数组指针  表示parr指针  指向数组的指针
138     //只有一个指针int(*)[10]
139 
140     //上面两个用法相近 但是意义不一样
141     //指针数组
142     for (int i = 0; i < 10; i++)
143     {
144         arr[i] = (int*)malloc(sizeof(int)* 5);//给10个指针元素赋值  sizeof求大小  malloc要申请的堆内存的大小  意思是申请20个字节的大小的空间
145     //注意下越界问题
146     }
147     int**pp = arr;//二级指针和指针数组对应
148     //赋值之后使用和指针数组是一样的
149 
150     //占用的总内存  指针数组 10个int*  一个指针4字节 10*4+10*5*4=240字节  指针大小+堆区大小
151     //int brr[10][5]  10*5*4=200个字节
152     for (int i = 0; i < 10; i++)free(arr[i]);//循环释放内存
153     //数组存放在连续内存中
154     //申请堆内存的时候 单次申请的内存连续 多次申请的不一定连续
155     //申请堆内存后记得要释放
156     int darr[10][5];//二维数组
157     int(*pdarr)[5] = darr;//赋值数组名 数组指针
158     //用法和二维数组一样的  都是解引用两次
159 
160     //二级指针 和数组指针
161     //int **pp 可以用来对应一个指针数组名
162     //总结 指针数组名 二维数组名 二级指针 数组指针 都需要解引用两次 使用的时候比较相似 但是是有区别的
163     //malloc  返回指针的函数 指针函数
164     //函数指针 传参的时候用函数指针接收
165     //传参 调用函数  实参(函数名)  形参(函数指针)
166 
167 #endif
168 
169     //--01--fun(1, 2, 3, max);//z直接实参是函数名
170 #if    0
171     int test[10] = {43,21,78,98,12,23,56,67,99,10};
172     printf("排序前:\n");
173     for (int i = 0; i < 10; ++i)
174     {
175         printf("%d\t", test[i]);//排序前
176     }
177     printf("\n\n");
178     
179     printf("排序后:\n");
180     bull_sort(test, 10);
181     for (int i = 0; i < 10; ++i)
182     {
183         printf("%d\t",test[i]);//排序后
184     }
185     printf("\n\n");
186     
187     getchar();
188     return 0;
189 #endif
190 
191     int test[10] = { 43, 21, 78, 98, 12, 23, 56, 67, 99, 10 };
192     printf("测试一:\n");
193     printf("排序前:\n");
194     for (int i = 0; i < 10; ++i)
195     {
196         printf("%d\t", test[i]);//排序前
197     }
198     printf("\n\n");
199 
200     printf("排序后:\n");
201     bull_sort(test, 10,max);
202     for (int i = 0; i < 10; ++i)
203     {
204         printf("%d\t", test[i]);//排序后
205     }
206     printf("\n\n");
207     
208     printf("测试二:\n");
209     printf("排序后:\n");
210     bull_sort(test, 10, min);
211     for (int i = 0; i < 10; ++i)
212     {
213         printf("%d\t", test[i]);//排序后
214     }
215     printf("\n\n");
216 
217     getchar();
218     return 0;
219 }

 

其中涉及到冒泡排序:

优化前的代码:

 1 #include<stdio.h>
 2 #include<stdlib.h>
 3 
 4 void bull_sort(int arr[],int n)  //冒牌排序 arr是存放数据的数组 n是数组中元素个数
 5 {
 6     int temp;//中间变量
 7     for (int i = 0; i < n - 1; ++i)  //循环n-1轮 每轮沉底一个数字 控制循环次数
 8     {
 9         //排序过程
10         for (int j = 0; j < n-1; ++j)  //j<n&&j+1<n   防止越界  控制循环
11         {
12             if (arr[j] > arr[j + 1])  //从小到大排序 前面元素比后面元素大 交换
13             {//从大到小的排序 前面的元素比后面的元素小 交换
14                 temp = arr[j];
15                 arr[j] = arr[j+1];
16                 arr[j+1] = temp;//temp中间变量 用来交换
17             }
18         }
19         printf("第[%d]轮排序:", i);//第i轮排序
20         for (int k = 0; k < 10; ++k)
21         {
22             printf("%d\t", arr[k]);
23         }
24         printf("\n\n");
25     }
26 }
27 
28 int main()
29 {
30     int test[10] = {43,21,78,98,12,23,56,67,99,10};
31     printf("排序前:\n");
32     for (int i = 0; i < 10; ++i)
33     {
34         printf("%d\t", test[i]);//排序前
35     }
36     printf("\n\n");
37     
38     printf("排序后:\n");
39     bull_sort(test, 10);
40     for (int i = 0; i < 10; ++i)
41     {
42         printf("%d\t",test[i]);//排序后
43     }
44     printf("\n\n");
45     
46     getchar();
47     return 0;
48 }

 

优化后的代码:

 1 #include<stdio.h>
 2 #include<stdlib.h>
 3 
 4 int max(int a, int b)
 5 {
 6     return a > b;
 7 }
 8 int min(int a, int b)
 9 {
10     return a < b;
11 }
12 
13 void bull_sort(int arr[], int n, int(*p)(int,int))  //函数指针 用来控制从小到大还是从大到小 冒牌排序 arr是存放数据的数组 n是数组中元素个数
14 {
15     int temp;//中间变量
16     for (int i = 0; i < n - 1; ++i)  //循环n-1轮 每轮沉底一个数字 控制循环次数
17     {
18         //排序过程
19         //for (int j = 0; j < n-1; ++j)  //j<n&&j+1<n   防止越界  控制循环
20         for (int j = 0; j<n - 1-i;++j)//优化之后的算法 j<n - 1-i  可以减少比较次数
21         {
22             if (p(arr[j],arr[j + 1]))  //从小到大排序 前面元素比后面元素大 交换
23             {//从大到小的排序 前面的元素比后面的元素小 交换
24                 temp = arr[j];
25                 arr[j] = arr[j+1];
26                 arr[j+1] = temp;//temp中间变量 用来交换
27             }
28         }
29         printf("第[%d]轮排序:", i);//第i轮排序
30         for (int k = 0; k < 10; ++k)
31         {
32             printf("%d\t", arr[k]);
33         }
34         printf("\n\n");
35     }
36 }
37 
38 int main()
39 {
40     int test[10] = { 43, 21, 78, 98, 12, 23, 56, 67, 99, 10 };
41     printf("测试一:\n");
42     printf("排序前:\n");
43     for (int i = 0; i < 10; ++i)
44     {
45         printf("%d\t", test[i]);//排序前
46     }
47     printf("\n\n");
48 
49     printf("排序后:\n");
50     bull_sort(test, 10,max);
51     for (int i = 0; i < 10; ++i)
52     {
53         printf("%d\t", test[i]);//排序后
54     }
55     printf("\n\n");
56     
57     printf("测试二:\n");
58     printf("排序后:\n");
59     bull_sort(test, 10, min);
60     for (int i = 0; i < 10; ++i)
61     {
62         printf("%d\t", test[i]);//排序后
63     }
64     printf("\n\n");
65 
66     getchar();
67     return 0;
68 }

 

 

2019-03-20  18:02:32