【C语言入门篇】深入理解指针 (3)

【C语言入门篇】深入理解指针(3)

 🌈个人主页:开敲

🔥所属专栏:C语言

🌼文章目录🌼

1.qsort函数

2. 什么是回调函数

3.sizeof和strlen

    3.1 sizeof

    3.2 strlen

    3.3 sizeof和strlen对比

4. 数组和指针笔试题练习

    4.1 一维数组

    4.2 二维数组

    4.3 字符数组

    4.4 指针运算

1.qsort函数

  C语言qsort函数解析(详细易懂)-CSDN博客

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;
}

                   

                                                           深入理解指针 (完结)

                                                         为努力的自己鼓个掌吧~

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值