函数指针详解

        1.回调函数:

回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。

冒泡排序:(局限性:该冒泡排序数组只能排整型数

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<limits.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>

int bubble_sort(int arr[], int sz)
{
	int i = 0;
	for (i = 0; i < sz - 1; i++)
	{
		int j = 0;
		for (j = 0; j < sz - 1 - i; j++)
		{
			if (arr[j]>arr[j + 1])
			{
				int tmp = arr[j];
				arr[j ] = arr[j+1];
				arr[j + 1] = tmp;
			}
		}
	}
}
int main()
{
	int arr[] = { 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	bubble_sort(arr, sz);
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
	return 0;

}

 插入:void* pa的意思是没有类型的指针;int* pa是整型指针;char* pa是字符型指针;

void* pa的好处在于不会出现类型不匹配的警告。可以接收任何类型的地址----int  char等等。

void*类型的指针不能进行解引用操作(void没有具体的类型,解引用操作时不知道访问几个指针)

void*类型的指针不能进行加减的操作;

2.库函数qsort-------C语言中提供的库函数-------可以排序任意类型的数据;----quick sort快速排序

库函数qsort的头文件为               #include<stdlib.h>               

qsort函数的第一个参数:待排序数组的首元素地址;第二个参数:待排序数组的元素个数;第三个参数:待排序数组每个元素的大小--单位是字节;第四个参数:函数指针,比较两个元素所用函数的地址--这个函数使用者自己体现。函数指针的两个参数:待比较的两个元素的地址。

 使用库函数qsort快速进行排序(冒泡排序)

 对浮点型进行排序:

 结构体同样也可以打印:(比较年龄)但是比较名字不能直接用大于小于;

 因为名字是字符,所以名字按照顺序不可以直接用大于或者小于来比较:在此引用函数  strcmp进行字符的比较:        strcmp     函数使用时需要引用头文件     #include<string.h>

3.调用函数指针;熟悉数组指针、指针数组、函数指针的区别;

 尤其注意:函数指针的初始化,int(*pAdd)(int,int)=Add;  int 是指针类型--整型;*pAdd是指针;尤其注意后面(int,int)表示参数的类型;需要根据你定义的函数去确定;定义Add为int x,int y为整型,所以括号里面填(int,int)。

函数指针的数组:int(*parr[5])(int,int)=&parr;

指向函数指针数组的指针:int(*(*pparr)[5])(int,int)=&parr;

4.仿照qsort的功能定义bubble_sort函数实现冒泡排序:

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<limits.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>

int cmp_int(const void*e1, const void*e2)
{
	return *(int*)e1 - *(int*)e2;
}
void swap(char*buf1, char*buf2,int width)
{
	int i = 0;
	for (i = 0; i < width; i++)
	{
		char tmp = *buf1;
		*buf1 = *buf2;
		*buf2 = tmp;
		*buf1++;
		*buf2++;
	}
}
void bubble_sort(void* base, int sz, int width, int(*cmp)(void* e1, void* e2))//仿照qsort函数的方式
{//void*base表示首元素的地址;int width表示被传数组元素的大小;int(*cmp)(void* e1, void* e2)表示指针
	int i = 0;
	for (i = 0; i < sz - 1; i++)
	{
		int j = 0;
		for (j = 0; j < sz - 1 - i; j++)
		{//两个元素作比较,进行交换
			if (cmp((char*)base + j*width, (char*)base + (j + 1)*width) > 0)
			{//强制类型转换为char*可以进行加减法;+j*width表示一直向后循环
				swap((char*)base + j*width, (char*)base + (j + 1)*width, width);
			}//因为不知道需要交换几次,所以需要把width也传过去
		}
	}
}
void test()
{
	int arr[] = { 7, 8, 9, 10,11, 2, 3, 4, 5, 6, 100 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	bubble_sort(arr, sz, sizeof(arr[0]), cmp_int);
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
}
int main()
{
	test();
	return 0;
}

注意:之所以强制类型转换为char*,是因为char*可以进行运算。

bubble_sort函数是cmp_sort,所以上边必须用*cmp指针来接收;

5.   注意:数组名绝大多数是表示首元素的地址

但是有两种例外(切记)1. sizeof(数组名)----数组名表示整个数组;

                                        2. &数组名  ----数组名表示整个数组;

凡是地址:他的字节大小不是4就是8(切记)

int main()
{
	int a[] = { 1, 2, 3, 4 };//   sizeof(a)计算数组总大小,单位是字节;
	printf("%d\n", sizeof(a));//  16  4个元素,每个元素4个字节
	printf("%d\n", sizeof(a + 0));//4
	printf("%d\n", sizeof(*a));//4
	printf("%d\n", sizeof(a + 1));//4
	printf("%d\n", sizeof(a[1]));//4
	printf("%d\n", sizeof(&a));//4
	printf("%d\n", sizeof(*&a));//16
	printf("%d\n", sizeof(&a + 1));//4
	printf("%d\n", sizeof(&a[0]));//4
	printf("%d\n", sizeof(&a[0] + 1));//4
}

第一个:sizeof(a) 取出的是整个数组的大小;4个元素每个元素4个字节;

第二个:sizeof(a+0) 数组名这里表示首元素的地址,a+0还是首元素的地址;只要是地址就是4/8;

第三个:sizeof(*a)   数组名表示取出首元素的地址;*a就是首元素,所以还是4;

第四个:sizeof(a+1) 数组名表示首元素的地址,a+1还是首元素的地址;所以还是4;

第五个:sizeof(a[1]) 数组名表示第二个元素的地址;

第六个:sizeof(&a) 数组名表示数组的地址,还是地址;

第七个:sizeof(*&a)   &a表示整个数组的地址,解引用表示取出整个数组的地址,所以此时表示整个数组的大小;

第八个:sizeof(&a+1) &a是数组的地址,&a+1表示跳过整个数组;但还是地址;

第九个:sizeof(&a[0]) 数组名表示第一个元素的地址;

第十个:sizeof(&a[0]+1)数组名表示第二个元素的地址;

int main()
{
	char arr[] = { 'a', 'b', 'c', 'd', 'e', 'f' };
	printf("%d\n", sizeof(arr));//6
	printf("%d\n", sizeof(arr + 0));//4
	printf("%d\n", sizeof(*arr));//1
	printf("%d\n", sizeof(arr[1]));//1
	printf("%d\n", sizeof(&arr));//4
	printf("%d\n", sizeof(&arr + 1));//4
	printf("%d\n", sizeof(&arr[0] + 1));//4
}

第一个:数组名表示整个数组的大小,所以是6;

第二个:sizeof(arr+0)表示首元素的大小,a+0还是表示首元素的大小,所以是4/8;

第三个:sizeof(*arr) arr表示首元素的大小,*arr表示解引用首元素,所以表示第一个元素,所以是1;

第四个:sizeof(arr[1]) arr[1]表示第二个元素,所以是1;

第五个:sizeof(&arr)  &arr表示整个数组的地址,所以不是4就是8;

第六个:sizeof(&arr+1) &arr表示整个数组的地址,&arr+1表示跳过整个数组,还是地址;

第七个:sizeof(&arr[0]+1) &arr[0]表示首元素的地址,&arr[0]+1表示第二个元素的地址,还是4/8;

int main()
{
	char arr[] = { 'a', 'b', 'c', 'd', 'e', 'f' };//strlen找结束符\0;
	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));//随机-6
	printf("%d\n", strlen(&arr[0] + 1));//随机-1
}

切记:strlen和sizeof的区别:sizeof是数组的大小,单位是字节;strlen是字符的长度,一定要找到\0结束标志才会结束;

第一个:arr表示整个数组,没有\0结束标志,所以是随机值;

第二个:arr+0表示首元素地址,+0还是随机值;

第三个:*arr,表示解引用首元素的地址,打印%d转成数值,error;

第四个:arr[1]表示第二个字符,打印%d还是数值,error;

第五个:&arr表示整个数组的地址,没有\0,还是随机值;

第六个:&arr+1表示在首元素的基础上,跳过一个数组,所以是随机值-6;6表示数组中原本存在的6个字符;

第七个:&arr[0]+1表示首元素+1,是第二个元素,所以从第二个元素开始,是首元素-1;

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值