当前位置:   article > 正文

41-数组 _ 数组作为函数参数

41-数组 _ 数组作为函数参数

41-1 冒泡排序函数的设计

数组传参的时候,形参有2种写法:

1、数组

2、指针

往往我们在写代码的时候,会将数组作为参数传个函数

如:实现一个冒泡排序,将数组的数据排成升序

冒泡排序的核心思想:

1、两个相邻的元素进行比较

2、一趟冒泡排序让一个数据来到它最终应该出现的位置上

动画演示:

总体思路:

1、n个元素需要n-1趟的冒泡排序(前n-1个元素的位置的确定了,最后一个元素的位置自然也确定了)

2、每一趟需要两两之间进行比较,确定一个元素的最终位置:n个元素,第一个元素需要比n-1次,第二个元素需要比n-2次……

那我们尝试写一下代码吧:

  1. //bubble_sort
  2. //形参采用数组的形式
  3. void bubble_sort(int arr[])
  4. {
  5. //趟数
  6. int sz = sizeof(arr) / sizeof(arr[0]);
  7. int i = 0;
  8. for (i = 0; i < sz - 1; i++)
  9. {
  10. //一趟冒泡排序
  11. int j = 0;
  12. for (j = 0; j < sz - 1 - i; j++)
  13. {
  14. if (arr[j] > arr[j + 1])
  15. {
  16. int tmp = 0;
  17. tmp = arr[j];
  18. arr[j] = arr[j + 1];
  19. arr[j + 1] = tmp;
  20. }
  21. }
  22. }
  23. }
  24. int main()
  25. {
  26. //冒泡排序:把数组排成升序
  27. int arr[10] = { 9,8,7,6,5,4,3,2,1,0 };
  28. //理想结果: 0 1 2 3 4 5 6 7 8 9
  29. int sz = sizeof(arr) / sizeof(arr[0]);
  30. //冒泡排序的算法,对数组进行排序
  31. bubble_sort(arr);
  32. int i = 0;
  33. for (i = 0; i < sz; i++)
  34. {
  35. printf("%d ", arr[i]);
  36. }
  37. return 0;
  38. }

错误!结果竟然没变!(X86)

X86结果:

X64结果: 

错误原因:在数组传参时,传的数组名本质上是数组首元素的地址,地址应该使用指针来接收,所以arr这里看似是数组,实质是指针。那么,这里sizeof(arr)是指针的大小,而不是整个数组的大小。以X86环境为例,一个指针(arr)的大小是4,一个元素(arr[0])的大小也是4,相除之后结果为1,1-1=0,无法进行循环,结果不会改变

所以我们直接传sz,不在函数中进行sz的计算

修改后的代码

  1. //bubble_sort
  2. //形参采用数组的形式
  3. void bubble_sort(int arr[],int sz)
  4. {
  5. //趟数
  6. int i = 0;
  7. for (i = 0; i < sz - 1; i++)
  8. {
  9. //一趟冒泡排序
  10. int j = 0;
  11. for (j = 0; j < sz - 1 - i; j++)
  12. {
  13. if (arr[j] > arr[j + 1])
  14. {
  15. int tmp = 0;
  16. tmp = arr[j];
  17. arr[j] = arr[j + 1];
  18. arr[j + 1] = tmp;
  19. }
  20. }
  21. }
  22. }
  23. int main()
  24. {
  25. //冒泡排序:把数组排成升序
  26. int arr[10] = { 9,8,7,6,5,4,3,2,1,0 };
  27. //理想结果: 0 1 2 3 4 5 6 7 8 9
  28. int sz = sizeof(arr) / sizeof(arr[0]);
  29. //冒泡排序的算法,对数组进行排序
  30. bubble_sort(arr,sz);
  31. int i = 0;
  32. for (i = 0; i < sz; i++)
  33. {
  34. printf("%d ", arr[i]);
  35. }
  36. return 0;
  37. }

成功啦~~~

41-2 数组名是什么

41-2-1 一维数组的数组名

让我们来验证一下数组名究竟是不是首元素地址吧:

  1. int main()
  2. {
  3. int arr[10];
  4. printf("%p\n", arr);
  5. printf("%p\n", &arr[0]);
  6. return 0;
  7. }

arr的地址果然与首元素地址一样: 

啊?那我们之前为什么说sizeof(arr)指的是整个数组的大小?

  1. int main()
  2. {
  3. int arr[10];
  4. int n = sizeof(arr);
  5. printf("%d\n", n);
  6. return 0;
  7. }

结果是40而不是4:

数组名能确实表示首元素的地址

但是有两个例外:

1、sizeof(数组名),这里的数组名表示整个数组,计算的是整个数组的大小,单位是字节

2、&数组名,这里的数组名表示整个数组,取出的是整个数组的地址

代码测试:

  1. int main()
  2. {
  3. int arr[10];
  4. printf("%p\n", arr);
  5. printf("%p\n", &arr[0]);
  6. printf("%p\n", &arr);
  7. return 0;
  8. }

输出结果: 

数组的地址是从首元素开始的,所以数组的地址跟首元素的地址一样

我们再加个1试一下:

  1. int main()
  2. {
  3. int arr[10] = {0};
  4. printf("%p\n", arr); //arr就是首元素的地址
  5. printf("%p\n", arr+1);
  6. printf("-----------\n");
  7. printf("%p\n", &arr[0]); //首元素的地址
  8. printf("%p\n", &arr[0]+1);
  9. printf("-----------\n");
  10. printf("%p\n", &arr); //数组的地址
  11. printf("%p\n", &arr+1);
  12. printf("-----------\n");
  13. return 0;
  14. }

结果如下:

前两个都是相差4,隔了一个元素的大小;而最后一个相差0x28,转换为十进制即为40,隔了整个数组的大小 

综上,前面的代码也可以这样写:(形参采用指针形式)

  1. //bubble_sort
  2. //形参采用指针的形式
  3. void bubble_sort(int* arr,int sz)
  4. {
  5. //趟数
  6. int i = 0;
  7. for (i = 0; i < sz - 1; i++)
  8. {
  9. //一趟冒泡排序
  10. int j = 0;
  11. for (j = 0; j < sz - 1 - i; j++)
  12. {
  13. if (arr[j] > arr[j + 1])
  14. {
  15. int tmp = 0;
  16. tmp = arr[j];
  17. arr[j] = arr[j + 1];
  18. arr[j + 1] = tmp;
  19. }
  20. }
  21. }
  22. }
  23. int main()
  24. {
  25. //冒泡排序:把数组排成升序
  26. int arr[10] = { 9,8,7,6,5,4,3,2,1,0 };
  27. //理想结果: 0 1 2 3 4 5 6 7 8 9
  28. int sz = sizeof(arr) / sizeof(arr[0]);
  29. //冒泡排序的算法,对数组进行排序
  30. bubble_sort(arr,sz);
  31. int i = 0;
  32. for (i = 0; i < sz; i++)
  33. {
  34. printf("%d ", arr[i]);
  35. }
  36. return 0;
  37. }

结果依然正确:

41-2-2 二维数组的数组名

sizeof(arr)仍然指的是整个数组的大小:

  1. int main()
  2. {
  3. int arr[3][4] = { 0 };
  4. printf("%d\n", sizeof(arr));
  5. return 0;
  6. }

一共12个元素,每个元素4个字节:

二维数组的数组名也表示数组首元素的地址

那么二维数组的首元素是谁?是arr[0][0]吗?

不是!是arr[0],指的是第一行的地址,而不是第一行第一个的地址

我们用代码验证一下:

  1. int main()
  2. {
  3. int arr[3][4] = { 0 };
  4. printf("%p\n", arr);
  5. printf("%p\n", arr+1);
  6. return 0;
  7. }

结果如下:

相差0x10,即十进制的16,正好隔了一行 

41-2-3 计算一个二维数组的行数和列数

计算行数:整个数组的大小除以第一行的大小

  1. int main()
  2. {
  3. int arr[3][4] = { 0 };
  4. printf("行数为%d\n", sizeof(arr) / sizeof(arr[0]));
  5. return 0;
  6. }

 结果:

计算列数:一行的大小除以第一行第一个元素的大小

  1. int main()
  2. {
  3. int arr[3][4] = { 0 };
  4. printf("列数为%d\n", sizeof(arr[0]) / sizeof(arr[0][0]));
  5. return 0;
  6. }

 结果:

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

闽ICP备14008679号