C进阶:指针的进阶(2)

向右看齐 2023-10-13 17:35 182阅读 0赞

" class="reference-link">c5e2b281f1ac49e88739eb0536d4fbbd.png

引入:

上一篇博文我们已经学习了字符指针,指针数组,数组指针有关知识,下面我们将对其展开讲一些重要的相关知识,欢迎各位观众老爷的观看。

&数组名VS数组名

这个知识点我可能上篇博文写过了,不过挺重要的,所以我拿出来再讲一下。

对于一个数组:

int arr[5];

arr和&arr分别是啥?

我们之前讲过arr在大部分情况下代表首元素的地址

所以这里还有两个例外:

1.sizeof数组名,这里数组名不是数组首元素地址,而是整个数组,其计算的是整个数组的大小(单位:字节)

2.还有一个就是我们要讲的&arr;

我们来看下面一段代码:

  1. #include <stdio.h>
  2. int main()
  3. {
  4. int arr[5] = { 0 };
  5. printf("%p\n", arr);
  6. printf("%p\n", &arr);
  7. return 0;
  8. }

63105bfe82fd42958b6a35733f517202.png

可见两个结果是相同的。难道说两个是一样的吗?

我们再来看一个代码:

  1. #include <stdio.h>
  2. int main()
  3. {
  4. int arr[5] = { 0 };
  5. printf("%p\n", arr);
  6. printf("%p\n", arr + 1);
  7. printf("%p\n", &arr);
  8. printf("%p\n", &arr + 1);
  9. return 0;
  10. }

17412e8e1c0644d8ad0b959d94a4a2b0.png

从上述代码我们显然可见:

1.从arr到arr+1的跨度是四个字节,也就是一个int单位。

2.从&arr到&arr+1的跨度是20个字节,也就是5个int单位。

因此不难得出:

第一种是跨过了数组中的一个单位,第二个而是直接跨过了一个数组。

数组参数,指针参数

在写代码时我们难免要把【数组】或者【指针】传给函数,那函数的参数该如何设计呢?

下面通过不同情况的几种例子,我们来看一下它们是怎么传参的。

数组的传参

一维数组传参

  1. #include<stdio.h>
  2. void test(int arr[])//ok?
  3. {}
  4. //ok 这种属于直接将数组作为参数,且一维数组中[]中内容可省略
  5. void test(int arr[10])//ok?
  6. {}
  7. //ok 这种属于直接将数组作为参数
  8. void test(int* arr)//ok?
  9. {}
  10. //ok 传过来的数组名是首元素地址,所以可以用一级指针来接收
  11. void test2(int *arr[20])//ok?
  12. {}
  13. //ok 直接用数组指针作参数,类型一致
  14. void test2(int** arr)//ok?
  15. {}
  16. //ok 由于该数组指针每个元素的类型为int*类型,所以我们这里用二级指针接收一级指针取出的地址
  17. int main()
  18. {
  19. int arr[10] = { 0 };
  20. int* arr2[20] = { 0 };
  21. test(arr);
  22. test2(arr2);
  23. return 0;
  24. }

二维数组传参

  1. #include <stdio.h>
  2. void test(int arr[3][5])//ok?
  3. {}
  4. //ok 直接以二维数组的原形式作为参数
  5. void test(int arr[][])//ok?
  6. {}
  7. //no 行和列都没有提供无法根据参数构建出原来的二维数组
  8. void test(int arr[][5])//ok?
  9. {}
  10. //ok 二维数组传参可以省略行但同时不能省略列
  11. //总结:二维数组传参,函数形参的设计只能省略第一个[]中的数字
  12. //因为对于一个二维数组,可以不知道有多少行,但必须知道一行有多少元素
  13. void test(int* arr)//ok?
  14. {}
  15. //no 该参数表示的是一行的元素
  16. void test(int* arr[5])
  17. {}
  18. //no 该形式参数为指针数组
  19. void test(int (*arr)[5])
  20. {}
  21. //yes 该形参为数组指针,指向一行,每一行有五个元素
  22. void test(int** arr)
  23. {}
  24. //no 二级指针接收的是一级指针的地址,而传来的是二维数组
  25. int main()
  26. {
  27. int arr[3][5] = { 0 };
  28. test(arr);
  29. return 0;
  30. }

指针传参

  1. #include <stdio.h>
  2. void print(int* p, int sz)
  3. {
  4. int i = 0;
  5. for (i = 0; i < sz; i++)
  6. {
  7. printf("%d ", *(p + i));
  8. }
  9. }
  10. int main()
  11. {
  12. int arr[10] = { 1,2,3,4,5,6,7,8,9 };
  13. int* p = arr;
  14. int sz = sizeof(arr) / sizeof(arr[0]);
  15. //一级指针p,传给函数
  16. print(p, sz);
  17. return 0;
  18. }

思考:

当一个函数的参数部分为一级指针时,函数能接受什么参数?

1.与它类型相同的指针。

2.一个数组。

3.一个数的地址。

下面是一些例子:

  1. //情况一:(10是另一个随机参数)
  2. int a = 10;
  3. int *p = &a;
  4. print(p1, 10);
  5. //情况二:
  6. int arr[4] = {0};
  7. print(arr, 10);
  8. //情况三:
  9. int a = 10;
  10. print(&a, 10);

二级指针传参

  1. #include<stdio.h>
  2. void test(int** ptr)
  3. {
  4. printf("%d\n", **ptr);
  5. }
  6. int main()
  7. {
  8. int n = 10;
  9. int* p = &n;
  10. int** pp = &p;
  11. test(pp);
  12. test(&p);
  13. //结果:两个都是10
  14. return 0;
  15. }

思考:

当函数的参数是二级指针的时候,可以接收什么参数?

1.一级指针的地址

2.与它相同的指针

好啦,这一期就到这里,感谢各位未来的大厂员工观看,谢谢!

发表评论

表情:
评论列表 (有 0 条评论,182人围观)

还没有评论,来说两句吧...

相关阅读

    相关 C指针(一)

    > 大家好,我是深鱼~ 【前言】: 指针的主题,在初阶指针章节已经接触过了,我们知道了指针的概念: 1.指针就是个变量,用来存放地址,地址的唯一标识一块内存空间(指针变量