【C语言入门篇】深入理解指针(3)
🌈个人主页:开敲
🔥所属专栏:C语言
🌼文章目录🌼
1.qsort函数
2. 什么是回调函数
回调函数就是通过函数指针调用的函数。
来看一段代码:
void menu()
{
printf("*****************************************\n");
printf("************ 1. Add 2. Sub ************\n");
printf("************ 3. Div 4. mul ************\n");
printf("************ 0. exit ************\n");
printf("*****************************************\n");
}
int Add(int x, int y)
{
return x + y;
}
int Sub(int x, int y)
{
return x - y;
}
int Div(int x, int y)
{
return x / y;
}
int Mul(int x, int y)
{
return x * y;
}
int main()
{
int x = 0;
int y = 0;
int input = 0;
do
{
menu();
printf("请选择:");
scanf("%d", &input);
switch (input)
{
case 1:
printf("请输入操作数:");
scanf("%d %d", &x, &y);
int ret = Add(x,y);
printf("%d\n", ret);
break;
case 2:
printf("请输入操作数:");
scanf("%d %d", &x, &y);
int ret1 = Sub(x, y);
printf("%d\n", ret1);
break;
case 3:
printf("请输入操作数:");
scanf("%d %d", &x, &y);
int ret2 = Div(x, y);
printf("%d\n", ret2);
break;
case 4:
printf("请输入操作数:");
scanf("%d %d", &x, &y);
int ret3 = Mul(x,y);
printf("%d\n", ret3);
break;
case 0:
printf("退出程序\n");
break;
}
} while (input);
return 0;
}
这段代码的作用是实现简易计算器,可以进行简单的加减乘除运算。
可以看到,在主函数中,switch内的代码十分啰嗦,每个case内都有许多重复的语句,这样写出来的代码显然是不太好的,那么改如何优化呢?这里就需要使用到我们的回调函数来进行优化了。
先来看看优化后的代码:
void menu()
{
printf("*****************************************\n");
printf("************ 1. Add 2. Sub ************\n");
printf("************ 3. Div 4. mul ************\n");
printf("************ 0. exit ************\n");
printf("*****************************************\n");
}
int Add(int x, int y)
{
return x + y;
}
int Sub(int x, int y)
{
return x - y;
}
int Div(int x, int y)
{
return x / y;
}
int Mul(int x, int y)
{
return x * y;
}
void calc(int(*pf)(int, int))
{
int x = 0;
int y = 0;
printf("请输入操作数:");
scanf("%d %d", &x, &y);
int ret = pf(x, y);
printf("%d\n", ret);
}
int main()
{
int input = 0;
do
{
menu();
printf("请选择:");
scanf("%d", &input);
switch (input)
{
case 1:
calc(Add);
break;
case 2:
calc(Sub);
break;
case 3:
calc(Div);
break;
case 4:
calc(Mul);
break;
case 0:
printf("退出程序\n");
break;
}
} while (input);
return 0;
}
可以看到,优化后的代码,case后就只有一个calc函数,整个代码看起来简洁了许多。接下来我们来分析一下优化后的代码。
优化后的代码,唯一的区别就是创建了calc函数。在调用这个函数的时候,参数(实参)部分我们传的是加、减、乘、除的函数地址,因此,我们在定义函数的时候,形参部分用函数指针来接收。这么做的目的就是为了能够能够在calc函数里调用其它函数,使得代码更加简洁。
以调用Add函数为例,我们画图来理解:
pf指针接收了Add函数的地址,而后在calc函数内部通过pf调用Add函数,这里的Add函数就称为回调函数,也就是上面所说的通过函数指针调用的函数。
3.sizeof和strlen
3.1 sizeof
在学习操作符的时候,我们学习了sizeof操作符。sizeof是用来求变量所占空间的大小的,单位是字节。当操作的对象是类型时,计算的则是类型所占空间的大小。例如:
sizeof(x)就是计算变量所占空间大小,sizeof(int)就是计算类型所占空间大小。并且,sizeof在计算变量大小的时候,sizeof后的括号可以不加,但是计算类型大小的时候,后面的括号必须加上。
3.2 strlen
strlen是C语言的库函数,专门用来计算字符串中'\0'以前的字符个数,单位同样是字节,使用时需要包含<string.h>头文件。例如:
补充:在创建字符串时,最后一个字符后面默认带有一个'\0',只不过不显示。
如果在字符串中手动加上了'\0',就无法求出字符串的准确长度:
3.3 sizeof和strlen对比
1. sizeof是操作符,而strlen是库函数,在使用strlen时需要包含<string.h>头文件。
2. sizeof计算的是变量或类型所占空间的大小,单位是字节;strlen是专门用来计算字符串中'\0'以前的字符个数。
3. sizeof不关注变量存放的是什么内容;strlen关注字符串中'\0'的位置,如果字符串中手动添加了'\0',可能无法准确计算出字符串的长度。
4. 数组和指针笔试题练习
4.1 一维数组
int main()
{
int a[] = { 1,2,3,4 };
int a[] = { 1,2,3,4 };
printf("%d\n", sizeof(a));
printf("%d\n", sizeof(a + 0));
printf("%d\n", sizeof(*a));
printf("%d\n", sizeof(a + 1));
printf("%d\n", sizeof(a[1]));
printf("%d\n", sizeof(&a));
printf("%d\n", sizeof(*&a));
printf("%d\n", sizeof(&a + 1));
printf("%d\n", sizeof(&a[0]));
printf("%d\n", sizeof(&a[0] + 1));
return 0;
}
4.2 二维数组
int main()
{
int a[2][3] = { 1,2,3,4,5,6 };
int a[3][4] = { 0 };
printf("%d\n", sizeof(a));
printf("%d\n", sizeof(a[0][0]));
printf("%d\n", sizeof(a[0]));
printf("%d\n", sizeof(a[0] + 1));
printf("%d\n", sizeof(*(a[0] + 1)));
printf("%d\n", sizeof(a + 1));
printf("%d\n", sizeof(*(a + 1)));
printf("%d\n", sizeof(&a[0] + 1));
printf("%d\n", sizeof(*(&a[0] + 1)));
printf("%d\n", sizeof(*a));
printf("%d\n", sizeof(a[3]));
return 0;
}
4.3 字符数组
代码1:
int main()
{
char arr[] = { 'a','b','c','d','e','f' };
printf("%d\n", strlen(arr));
printf("%d\n", strlen(arr + 0));
printf("%d\n", strlen(*arr));
printf("%d\n", strlen(arr[1]));
printf("%d\n", strlen(&arr));
printf("%d\n", strlen(&arr + 1));
printf("%d\n", strlen(&arr[0] + 1));
return 0;
}
代码2:
int main()
{
char arr[] = "abcdef";
printf("%d\n", sizeof(arr));
printf("%d\n", sizeof(arr + 0));
printf("%d\n", sizeof(*arr));
printf("%d\n", sizeof(arr[1]));
printf("%d\n", sizeof(&arr));
printf("%d\n", sizeof(&arr + 1));
printf("%d\n", sizeof(&arr[0] + 1));
return 0;
}
4.4 指针运算
代码1:
int main()
{
int a[5] = { 1, 2, 3, 4, 5 };
int *ptr = (int *)(&a + 1);
printf( "%d,%d", *(a + 1), *(ptr - 1));
return 0;
}
代码2:
int main()
{
char *a[] = {"work","at","alibaba"};
char**pa = a;
pa++;
printf("%s\n", *pa);
return 0;
}
代码3:
int main()
{
char *c[] = {"ENTER","NEW","POINT","FIRST"};
char**cp[] = {c+3,c+2,c+1,c};
char***cpp = cp;
printf("%s\n", **++cpp);
printf("%s\n", *--*++cpp+3);
printf("%s\n", *cpp[-2]+3);
printf("%s\n", cpp[-1][-1]+1);
return 0;
}
深入理解指针 (完结)
为努力的自己鼓个掌吧~