当前位置:   article > 正文

嵌入式学习之路 14(C语言基础学习——指针操作一维整型数组)

嵌入式学习之路 14(C语言基础学习——指针操作一维整型数组)

一、指针基础

指针的概念

        地址表示内存单元的编号,也被称为指针。指针既是地址,也是一种专门用于处理地址数据的数据类型
例如,变量a的地址或者十六进制表示的0x1000都可以视作指针。
 

指针变量的定义

语法:基类型 * 指针变量名。
        基类型可以是之前学过的各种数据类型,如整型、浮点型、字符型、结构体类型、函数类型等,它表示指针所指向的内存空间能够存放的数据类型。例如:int *p; 中,p就是一个指向整型数据的指针变量。
        *在定义时表示定义的是指针类型的变量。
        指针变量名需符合标识符命名规则。


指针类型

例如:在int *p;中,int *整体被称为指针类型,表示指向整型数据的指针类型。


指针变量的引用

例如:int a = 10; int *p = &a; ,p指向 a 。
*是指针运算符,为单目运算,运算对象只能是指针(地址)。
*p表示访问 p 所指向的基类型的内存空间,这是一种间接访问。其过程包括:首先拿出 p 中的地址,在内存中定位;然后偏移出 sizeof(基类型) 大小的一块空间;最后将偏移出的这块空间当作一个基类型变量来看。
例如,*p 的运算效果相当于直接访问的变量 a 。
类似地,对于int a; ,a的数据类型是 int ,&a的数据类型是 int* ,对于 float b; ,&b的数据类型是 float* 。


指针变量的初始化

如果指针变量没有初始化,此时的值是随机值(野指针)。
初始化可以让指针变量有明确的指向,例如:int a; int *p = &a; 或者 int *p = NULL(NULL 表示空指针,即 0 号地址)。


赋值

例如:int *p; p = &a;


定义多个指针变量

例如:int *p, *q; 表示定义了两个指针变量。
注意:定义时候的 * 是修饰变量名的,表示定义的是一个指针类型的变量。


为什么需要指针指针

指针可以实现被调函数修改主调函数中的数据。

二、指针作为函数的参数

1、形参是指针类型的变量,用来接收实参(实参是要操作的内存空间的地址)。
2、实参:要修改谁,就把谁的地址传进去,但要保证空间有效。
3、注意:被调函数中一定要有*p的运算(间接访问的操作)。
4、值传递只是实参数据赋值给了形参,而地址(指针传递)传递的是地址,可以实现被调修改主调。

练习:

  1. #include <stdio.h>
  2. // 函数:实现两个数相加,并将结果存储在指针所指的变量中
  3. void ADD(int *a, int b)
  4. {
  5. *a = *a + b; // 将指针 a 所指变量的值与 b 相加,并将结果存储回指针所指的变量
  6. }
  7. // 函数:找出两个数中的最大值和最小值,并通过指针返回
  8. void maxandmin(int a, int b, int *max, int *min)
  9. {
  10. *max = a > b? a : b; // 如果 a 大于 b,将 a 赋值给指针 max 所指的变量,否则将 b 赋值给它
  11. *min = a < b? a : b; // 如果 a 小于 b,将 a 赋值给指针 min 所指的变量,否则将 b 赋值给它
  12. }
  13. // 函数:交换两个指针所指变量的值
  14. void swap(int *a, int *b)
  15. {
  16. int temp = *a; // 临时变量 temp 存储指针 a 所指变量的值
  17. *a = *b; // 将指针 b 所指变量的值赋给指针 a 所指的变量
  18. *b = temp; // 将临时变量 temp 的值赋给指针 b 所指的变量
  19. }
  20. // 主函数
  21. int main()
  22. {
  23. int a = 2; // 定义并初始化变量 a 为 2
  24. int b = 3; // 定义并初始化变量 b 为 3
  25. int max; // 定义变量用于存储最大值
  26. int min; // 定义变量用于存储最小值
  27. // ADD(&a,b); // 调用 ADD 函数,将 b 的值加到 a 上
  28. // printf("sum = %d\n",a); // 输出相加后的结果
  29. // maxandmin(a,b,&max,&min); // 调用 maxandmin 函数找出 a 和 b 的最大值和最小值
  30. // printf("max = %d, min = %d\n",max,min);
  31. printf("a = %d b = %d\n",a,b); // 输出原始的 a 和 b 的值
  32. swap(&a,&b); // 调用 swap 函数交换 a 和 b 的值
  33. printf("a = %d b = %d\n",a,b); // 输出交换后的 a 和 b 的值
  34. return 0;
  35. }

三、指针与一维整型数组

1、数组名代表数组首元素的地址,就是数组所在空间的首地址。例如:定义一个指向整型数组的指针变量可以写成 int *p = a; 或者 int *p = &a[0]; ,表示 p 指向了数组 a 。
2、数组名(数组首元素的地址)和 &a[0] 等价。
3、*p 等价于 a[0] 。
4、指针的运算:

&:取地址运算符。
*:解引用运算符。
p + 1:指针的算术运算,其偏移量取决于指针所指向的数据类型的大小。

指针的比较:

>  >=  <  <=  ==  !=

可以比较两个指针的大小或相等关系,但前提是这两个指针指向同一个数组或具有相同的基类型。

  1. #include <stdio.h>
  2. // 函数:打印数组元素
  3. void printfArray(int *begin, int *end)
  4. {
  5. // 只要起始指针不超过结束指针,就持续执行循环
  6. while (begin <= end)
  7. {
  8. // 打印起始指针所指向的元素,并将起始指针向后移动一位
  9. printf("%d ",*begin++);
  10. }
  11. // 换行,使输出更清晰
  12. printf("\n");
  13. }
  14. // 函数:找出数组中的最大值
  15. int maxArray(int *a, int len)
  16. {
  17. int i; // 定义循环变量
  18. // 初始化最大值为数组的第一个元素
  19. int max = *a;
  20. // 遍历数组的每一个元素
  21. for (i = 0; i < len; i++)
  22. {
  23. // 如果当前最大值小于数组中的某个元素
  24. if (max < *(a + i))
  25. {
  26. // 更新最大值为该元素
  27. max = *(a + i);
  28. }
  29. }
  30. // 返回最大值
  31. return max;
  32. }
  33. // 函数:反转数组元素的顺序
  34. void reversedOrder(int *begin, int *end)
  35. {
  36. int temp; // 定义临时变量用于交换元素
  37. // 只要起始指针小于结束指针,就持续执行循环
  38. while(begin < end)
  39. {
  40. // 交换起始指针和结束指针所指向的元素
  41. temp = *begin;
  42. *begin = *end;
  43. *end = temp;
  44. // 起始指针向前移动一位
  45. begin++;
  46. // 结束指针向后移动一位
  47. end--;
  48. }
  49. }
  50. // 函数:选择排序
  51. void choieSort(int *begin, int *end)
  52. {
  53. int *p = begin; // 定义指向起始位置的指针
  54. int *q = NULL; // 定义用于遍历的指针
  55. // 外层循环控制排序的轮数
  56. for (p = begin; p < end; p++)
  57. {
  58. // 内层循环在每一轮中找出最小元素
  59. for (q = p + 1; q <= end; q++)
  60. {
  61. // 如果当前元素大于后面的元素
  62. if (*p > *q)
  63. {
  64. // 交换两个元素
  65. int t = *p;
  66. *p = *q;
  67. *q = t;
  68. }
  69. }
  70. }
  71. }
  72. // 函数:冒泡排序
  73. void bubbleSort(int *begin, int *end)
  74. {
  75. int *p = begin; // 定义指向起始位置的指针
  76. int *q = NULL; // 定义用于遍历的指针
  77. // 外层循环控制排序的轮数
  78. for (p = end; p > begin; p--)
  79. {
  80. // 内层循环在每一轮中比较相邻元素
  81. for (q = begin; q < p; q++)
  82. {
  83. // 如果当前元素大于下一个元素
  84. if (*q > *(q + 1))
  85. {
  86. // 交换两个相邻元素
  87. int t = *q;
  88. *q = *(q + 1);
  89. *(q + 1) = t;
  90. }
  91. }
  92. }
  93. }
  94. // 函数:插入排序
  95. void insertSort(int *begin, int *end)
  96. {
  97. int *p = begin; // 定义指向起始位置的指针
  98. int *q = NULL; // 定义用于遍历的指针
  99. // 从第二个元素开始遍历
  100. for (p = begin + 1; p <= end; p++)
  101. {
  102. int t = *p; // 保存当前要插入的元素
  103. q = p; // 记录当前位置
  104. // 寻找插入位置
  105. while (q > begin && *(q - 1) > t)
  106. {
  107. // 将较大的元素向后移动
  108. *q = *(q - 1);
  109. q--; // 指针向前移动
  110. }
  111. // 插入元素
  112. *q = t;
  113. }
  114. }
  115. // 函数:折半查找
  116. int * binaryFind(int *begin, int *end, int n)
  117. {
  118. int *mid = NULL; // 定义指向中间位置的指针
  119. int *ret = NULL; // 定义用于存储查找结果的指针
  120. // 只要查找范围存在(起始指针小于等于结束指针)
  121. while (begin <= end)
  122. {
  123. // 计算中间位置
  124. mid = begin + (end - begin) / 2;
  125. // 如果要查找的值小于中间值
  126. if (n < *mid)
  127. {
  128. // 在左半部分继续查找
  129. end = mid - 1;
  130. }
  131. // 如果中间值小于要查找的值
  132. else if (*mid < n)
  133. {
  134. // 在右半部分继续查找
  135. begin = mid + 1;
  136. }
  137. // 如果找到匹配的值
  138. else
  139. {
  140. // 记录找到的位置
  141. ret = mid;
  142. break; // 退出循环
  143. }
  144. }
  145. // 返回查找结果,如果未找到则为 NULL
  146. return ret;
  147. }
  148. // 函数:折半查找(递归)
  149. int *binaryFindR(int *begin, int *end, int n)
  150. {
  151. int *mid = begin + (end - begin) / 2; // 计算中间位置
  152. int *ret = NULL; // 定义用于存储查找结果的指针
  153. // 如果起始指针大于结束指针,说明未找到
  154. if (begin > end)
  155. {
  156. return NULL;
  157. }
  158. // 如果要查找的值小于中间值
  159. if (n < *mid)
  160. {
  161. // 在左半部分递归查找
  162. end = mid - 1;
  163. ret = binaryFindR(begin, end, n);
  164. }
  165. // 如果中间值小于要查找的值
  166. else if (*mid < n)
  167. {
  168. // 在右半部分递归查找
  169. begin = mid + 1;
  170. ret = binaryFindR(begin, end, n);
  171. }
  172. // 如果找到匹配的值
  173. else if (*mid == n)
  174. {
  175. // 记录找到的位置
  176. ret = mid;
  177. }
  178. // 返回查找结果,如果未找到则为 NULL
  179. return ret;
  180. }
  181. // 函数:交换两个指针所指向的值
  182. void swap(int *a, int *b)
  183. {
  184. int t = *a; // 临时存储指针 a 所指向的值
  185. *a = *b; // 将指针 b 所指向的值赋给指针 a 所指向的位置
  186. *b = t; // 将临时存储的值赋给指针 b 所指向的位置
  187. }
  188. // 函数:快速排序
  189. void quickSort(int *begin, int *end)
  190. {
  191. // 记录起始位置和结束位置
  192. int *p = begin;
  193. int *q = end;
  194. // 选择起始位置的元素作为基准值
  195. int *k = begin;
  196. // 只要起始指针小于结束指针,就持续执行循环
  197. while (begin < end)
  198. {
  199. // 从右向左找小于基准值的元素
  200. while(begin < end && *end >= *k)
  201. {
  202. end--;
  203. }
  204. // 从左向右找大于基准值的元素
  205. while (begin < end && *begin <= *k)
  206. {
  207. begin++;
  208. }
  209. // 交换找到的两个元素
  210. swap(begin, end);
  211. }
  212. // 如果起始指针和结束指针相遇
  213. if (begin == end)
  214. {
  215. // 将基准值与相遇位置的元素交换
  216. swap(k, begin);
  217. }
  218. // 如果起始位置到结束位置减 1 的范围内还有元素,继续排序
  219. if (p < end - 1)
  220. {
  221. quickSort(p, end - 1);
  222. }
  223. // 如果起始位置加 1 到结束位置的范围内还有元素,继续排序
  224. if (begin + 1 < q)
  225. {
  226. quickSort(begin + 1, q);
  227. }
  228. }
  229. // 主函数
  230. int main()
  231. {
  232. int a[] = {10,2,8,5,4,6,7,3,9,1}; // 定义并初始化整数数组
  233. int len = sizeof(a)/sizeof(a[0]); // 计算数组的长度
  234. /*printf("max = %d\n",maxArray(a,len));
  235. printfArray(a,a+len-1); //可以改变打印的起始位置和结束位置
  236. reversedOrder(a,a+len-1);
  237. printfArray(a,a+len-1);*/
  238. //choieSort(a,a+len-1);
  239. //bubbleSort(a,a+len-1);
  240. printfArray(a,a+len-1);
  241. //insertSort(a,a+len-1);
  242. //printfArray(a,a+len-1);
  243. /*int n;
  244. scanf("%d",&n);
  245. //int *ret = binaryFind(a,a+len-1,n);
  246. int *ret = binaryFindR(a,a+len-1,n);
  247. if (ret==NULL)
  248. printf("no found\n");
  249. else
  250. printf("found\n");
  251. */
  252. quickSort(a,a+len-1); // 对数组进行快速排序
  253. printfArray(a,a+len-1); // 打印排序后的数组
  254. return 0;
  255. }

快速排序的思路 

5330fa9e787e422297929ba356da599e.png

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/秋刀鱼在做梦/article/detail/950698
推荐阅读
相关标签
  

闽ICP备14008679号