1.一维数组传参
有一个接受一维数组的函数为:
int arr[10]={0};
test(arr);
在传参的时候接受类型为
void test(int arr[])
{}
void test(int arr[10])
{}
void test(int *arr)
{}
void test(int *arr[10])
{}
void test(int **arr)
{}
2.二维数组传参
在传参过程中只能省略行标
#include<stdio.h>
void test(int arr[3][5])
{}
void test1(int arr[][5])
{}
void test2(int arr[3][])
{}
void test3(int (*arr)[5])
{}
int main()
{
int arr[3][5] = { 0 };
test(arr);
test1(arr);
test2(arr);
test3(arr);
return 0;
}
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]);
print(p, sz);
return 0;
}
4.函数指针
#include<stdio.h>
int add(int x, int y)
{
int z = 0;
return z = x + y;
}
void Print(char* str)
{
printf("%s\n", str);
}
int main()
{
int (*pa)(int*, int*) = add;
printf("%d\n", (*pa)(2,3));
void (*p)(char*) = Print;
(*p)("ni hao");
return 0;
}
函数指针有一个典型的陷阱代码
#include<stdio.h>
int main()
{
(*(void(*)())0)();//代码1
将0强制类型转换为void(*)(),0就成为一个函数地址,再调用0地址处的该函数
void(*signal(int, void(*)(int)))(int);//代码2
简化
typedef void(*lj_z)(int);
lj_z signal(int, lj_z);
signal是一个函数声明,有两个参数int和指针函数,该指针函数的参数为int,返回类型为void
signal的返回类型是一个函数指针,该指针函数的参数为int,返回类型为void
return 0;
}
在调用过程中传递类型广泛,例如
#include<stdio.h>
int add(int x, int y)
{
int z = 0;
return z = x + y;
}
int main()
{
int a = 2;
int b = 3;
int (*pa)(int, int) = add;
printf("%d\n", pa(2, 3));
printf("%d\n", add(2, 3));
printf("%d\n", (*pa)(2, 3));
printf("%d\n", (**pa)(2, 3));
printf("%d\n", (***pa)(2, 3));
用指针必须带(),*数量无所谓
printf("%d\n", *pa(2, 3));//err
return 0;
}
5.函数指针数组示例
#include<stdio.h>
int Add(int x, int y)
{
int z = 0;
return z = x + y;
}
int Sub(int x, int y)
{
int z = 0;
return z = x - y;
}
int Mul(int x, int y)
{
int z = 0;
return z = x * y;
}
int Div(int x, int y)
{
int z = 0;
return z = x / y;
}
int main()
{
int (*pa)(int, int) = Add;//也可以是Sub,Mul,Div;
所以需要一个数组来存放四个函数的地址--函数指针数组
int (*paarr[4])(int, int) = { Add,Sub,Mul,Div };
int i = 0;
for (i = 0; i < 4; i++)
{
printf("%d\n", paarr[i](4, 2));
}
return 0;
}
###实现计算器
#include<stdio.h>
void menu()
{
printf(" 1.Add 2.Sub \n");
printf(" \n");
printf(" \n");
printf(" 3.Mul 4.Div \n");
printf(" \n");
printf(" \n");
printf(" 5.Xor 0,Exit \n");
}
int Add(int x, int y)
{
int z = 0;
return z = x ^ y;
}
int Sub(int x, int y)
{
int z = 0;
return z = x - y;
}
int Mul(int x, int y)
{
int z = 0;
return z = x * y;
}
int Div(int x, int y)
{
int z = 0;
return z = x / y;
}
int Xor(int x, int y)
{
int z = 0;
return z = x ^ y;
}
int main()
{
int input = 0;
int (*com[6])(int, int) = { 0,Add,Sub,Mul,Div,Xor};
do
{
menu();
printf("请选择你需要的功能");
scanf_s("%d", &input);
if (input != 0)
{
printf("请输入需要处理的参数");
int x = 0, y = 0;
scanf_s("%d%d", &x, &y);
int result = com[input](x, y);
printf("%d\n", result);
}
else
{
break;
}
} while (input);
return 0;
}
6.回调函数
回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。
#include<stdio.h>
int ADD(int x, int y)
{
return x + y;
}
int calc(int(*p)(int x, int y))
{
printf("请输入两个参数");
int a = 0;
int b = 0;
scanf_s("%d%d", &a, &b);
printf("%d\n", p(a, b));
}
int main()
{
calc(ADD);
return 0;
}
上述代码中calc就作为回调函数,调用了ADD,可以用于解决代码冗杂问题。
7.指向函数指针数组的指针
#include<stdio.h>
int main()
{
int arr[10];//这是一个数组
int(*p)[10] = &arr;//取出数组的地址
int (*pf)(int ,int)//这是一个函数指针
int (*parr[10])(int, int);//这是一个函数指针数组
int(*(*pparr[10])(int, int)) = &parr;//指向函数指针数组的指针
//首先pparr和*结合说明是一个指针,与[]结合,说明是一个数组指针
//再与*结合说明用一个指针指向了数组指针
//之后又指向一个函数的入口地址,该函数有两个int类型参数,返回值是int
return 0;
}