指针
指针 存放地址 只能存放地址
使用
&取地址运算符 *取值 解引用运算符
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表示常量

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

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

 

 

 

代码笔记:

  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