1. 程式人生 > >C++學習(二十三)(C語言部分)之 指針4

C++學習(二十三)(C語言部分)之 指針4

個數字 函數類型 圖片 有意義 大小 堆排 傳參 不能 etc

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