前言
承接上篇,这期继续C语言指针的学习。
目录
Part4:数组参数&指针参数
1.一维数组传参
2.二维数组传参
3.一级指针传参
4.二级指针传参
Part5:函数指针
1.引入
2.表示
Part6:函数指针数组
1.引入
2.表示
3.应用
Part7:回调函数
1.定义
2.应用
正文
Part4:数组参数&指针参数
在敲代码时经常会有这样的情景:把【数组】或者【指针】传递给函数,那么函数该如何设计呢?这一部分会解答这个问题。
1.一维数组传参
我将用这段代码来测试传参的正确姿势:
int main() { int arr1[10] = { 0 }; int* arr2[20] = { 0 }; test1(arr1); test2(arr2); return 0; }
看下列传参方式是否可行:
1. void test1(int arr[]) 2. {} 3. // 可行:传数组,用数组接收,可以不指定大小
void test1(int arr[10]) {} // 可行:传数组,用数组接收,大小保持一致
void test1(int* arr) {} // 可行:数组名代表首元素地址,用指针接收
void test2(int* arr[]) {} // 可行:传递指针数组,用指针数组接收,可以不指定大小
void test2(int* arr[20]) {} // 可行:传递指针数组,用指针数组接收,大小保持一致
void test2(int** arr) {} // 可行:数组名代表首元素地址,首元素类型是 int* ,地址类型是二级指针 int**
总结:一维数组传参,要么用数组接收, 要么用指针接收
2.二维数组传参
测试代码:
int main() { int arr[3][5] = { 0 }; test(arr); }
看下列传参方式是否可行:
void test(int arr[3][5]) {} // 可行:相同形式接收
void test(int arr[][5]) {} // 可行:指定列必须,行可以省略
void test(int arr[][]) {} // 不可行:没有指定列
void test(int* arr) {} // 不可行:传递的二维数组,起码用首行的地址接收
void test(int* arr[5]) {} // 不可行:形参表示指针数组,与实参数组的类型不匹配
void test(int(*arr)[5]) {} // 可行:表示第一行的地址
void test(int** arr) {} // 不可行:形参表示二级指针,不可接受二维数组
总结:
二维数组传参,函数形参若为数组类型,其设计只能省略第一个[ ] 的数字,
因为对一个二维数组,可以不知道有多少行,但是必须知道一行多少元素。
若为指针类型,是第一行的地址
3.一级指针传参
一级指针传参简单,用一级指针接收就好了。
下面是例子:
#include <stdio.h> void print(int *p, int sz) { int i = 0; for(i=0; i<sz; i++) { printf("%d\n", *(p+i)); } } int main() { int arr[10] = {1,2,3,4,5,6,7,8,9}; int *p = arr; int sz = sizeof(arr)/sizeof(arr[0]); //一级指针p,传给函数 print(p, sz); return 0; }
👁️🗨️输出结果:
没意思吧?
那我们反过来想:当形参是一级指针的时候,函数能接收什么参数?
void test(int *p) {} // test函数能接收什么参数?
int a = 10; int* p = &a; int arr[10]; // 接收以下参数 test(&a); test(p); test(arr);
4.二级指针传参
同一级指针,二级指针传参,二级指针接收就行了。
例子:
void test(int** ptr) { printf("num = %d\n", **ptr); } int main() { int n = 10; int* p = &n; int** pp = &p; test(pp); test(&p); return 0; }
👁️🗨️输出结果:
反过来想: 当形参是二级指针的时候,函数能接收什么参数?
void test(int** pp) {} // 能接收什么参数?
int a = 10; int* pa = &a; int** ppa = &pa; int* arr[10]; // 接收以下参数 test(&pa); test(ppa); test(arr);