C++學習(二十三)(C語言部分)之 指針4
指針
指針 存放地址 只能存放地址
使用
&取地址運算符 *取值 解引用運算符
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
C++學習(二十三)(C語言部分)之 指針4