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