指针的进阶

目录

 

一、指针数组

二、数组指针

​编辑三、数组参数、指针参数

1.数组传参:形参可以使数组,也可以是指针

2、 二维数组传参:​编辑

3、一 二级指针传参

 四、函数指针

五、函数指针数组

六、指向函数指针数组的指针 

七、回调函数


 

一、指针数组

指针数组是一个存放指针的数组

 int* arr1[10]; //整型指针数组

char *arr2[4]; //一级字符指针数组;

char **arr3[5]; //二级字符指针数组;

二、数组指针

2985a240d4ce4157883e61426d858950.png

// p先和*结合,说明p是一个变量,然后指针指向的是一个大小卫视的整型的数组。所以p是一个指针,指向一个数组,叫数组指针。

//需要注意的是:[ ]的优先级要高于‘*’的,所以必须加上()来保证p先和‘*’结合。

数组指针的使用:

5efcd96475054a2d8158d55e7f5aa3a0.png三、数组参数、指针参数

1.数组传参:形参可以使数组,也可以是指针

033526137efd4861839b6a69ae2fd425.png

2、 二维数组传参:720a3f4356e1480aac1cd23387828098.png

 

3、一 二级指针传参

dce03667c87e45a7833d162fb87ffc9d.png

 

3ee852fe35014d27894ee604e009e728.png

 四、函数指针

d123c09fbfa94698bb746c004d3f3798.png

 //pf用于存放Add的地址,*pf中的 * 可以省略,*并不是语法需求,且 * 的多少对结果的输出没有影响。

拓展:

1、(*( void(*)()0 )()

//( void(*)() )0 —把0当做一个函数的地址,强制把0转换成一个void(*)()函数指针,然后去调用0地址出的函数

2、void( *signal( int, void(*)(int) ) ) (int)

     typedef void(*pf_t)(int)   //因为语法要求不能写为typedef void(*)(int) pf_t

     void(*signal(int ,pf_t)(int)-->pf_t signal(int ,pf_t)

//上述代码是一次函数声明

//声明函数叫:signal

//siganl函数的第一个参数是int类型的

//signal函数的第二个参数是一个函数指针类型,该函数指针指向的函数参数是int,返回类型是void

//signal函数的返回类型也是一个函数指针类型,该函数指针指向的函数参数是int,返回类型是void

五、函数指针数组

f2ad4102cf5b4cbc88be7d456a80c84c.png

在一定情况下(参数相同、返回类型相同)可代替switch

六、指向函数指针数组的指针 

81d66307e9ea4fdd835b657ba7243f08.png

 86a99e965cb548da96e4934e8af733b2.png

七、回调函数

回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个 函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。回调函数不是由该函数 的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进 行响应。

引入:qsort函数

qsort 可以排序任意类型的数据

void qsort (void* base,  //待排序数据的起始地址

                    size_t num, //待排序的元素个数

                    size_t size, //待排序的元素大小(单位是字节)

                    int (*cmp)(const void*,cons void*) //比较2个元素大小的指针,值得注意的是                        //对于不同的元素种类,比较方式也就不同。此处可调用自己所编写的比较函数。

                   );

对于两个元素的大小比较,如果第一个指针大于第二个指针指向的元素时,返回1

                                           如果第一个指针等于第二个指针指向的元素时,返回0

                                           如果第一个指针小于第二个指针指向的元素时,返回-1         

qsort 的使用:

feb79e33459c45158d1a888307214640.png

结构体:

6a97bc1b33c7484ea011484cf6f6d4ca.png

 

 对于升序和降序可以控制比较函数中的返回值

 使用回调函数模拟sqort函数

#include<stdio.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_sort2(void* base, int sz, int width, int (*cmp)(const void* e1, const void* e2))
{
	int i = 0;
	//趟数
	for (i = 0; i < sz - 1; i++)
	{
		//一趟冒泡排序的过程
		int j = 0;
		for (j = 0; j < sz - 1 - i; j++)
		{
			//强制类型转换为char类型,因void类型指针不能解引用
			if (cmp((char*)base + j * width, (char*)base + (j + 1) * width) > 0)
			{
				//交换
				Swap((char*)base + j * width, (char*)base + (j + 1) * width, width);//width为元素大小
			}
		}
	}
}
void print(int arr[], int sz)
{
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
	printf("\n");
}

void test4()
{
	int arr[] = { 486,589,849,648,797,974,8595 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	bubble_sort2(arr, sz, sizeof(arr[0]), cmp_int);
	print(arr, sz);
}
int main()
{
	test4();
	return 0;
}

模拟实现qsort排序字符串

int compare_string_func(const void* e1, const void* e2)
{
    int ret = strcmp(*(char**)e1, *(char**)e2);//e1接收的元素类型为char*(数组元素地址强制类型转换的)
    //由于需要传入字符串地址,强制类型转换为二级指针,此时e1相当于二级指针,字符串的地址相当于一级指针所指对象
    //e1存放一级指针地址,解引用获得一级指针所含内容,即字符串地址
    return ret;
}
void swap(char* buf1, char* buf2, int n)//buf1,buf2接收的为【数组元素地址(强制类型转换为char*)】的地址
{
    for (int i = 0; i < n - 1; i++)
    {
        char tmp = *buf1;//解引用获得数组元素地址进行交换,交换后,地址中所含内容也随之交换,即字符串的地址
        *buf1 = *buf2;
        *buf2 = tmp;
        buf1++;
        buf2++;
    }
}
void my_qsort(void* base, int sz, int n, int(*cmp_func)(const void*, const void*))//base接收元素地址
{
    for (int i = 0; i < sz - 1; i++)
    {
        for (int j = 0; j < sz - i - 1; j++)
        {
            if (cmp_func((char*)base + j * n, (char*)base + (j + 1) * n) > 0)//将元素地址强制类型转换为char*,每加
                //n个字节,跳过一个元素地址,找到下一个元素地址
            {
                swap((char*)base + j * n, (char*)base + (j + 1) * n, n);
            }
        }
    }
}
void print(char* arr[], int sz) {
    for (int i = 0; i < sz; i++) {
        printf("%s\n", arr[i]);
    }
}
#include<stdio.h>
#include<stdlib.h>
int main()
{
    char* arr[] = { "zhangsan","lisi","wangwu" };//数组中元素类型地址,数组本身仍需开辟地址,用来存放元素->字符串地址
     // 求出数组中的元素个数,使用数组的内存长度 / 第一个元素的内存长度
    int sz = sizeof(arr) / sizeof(arr[0]);
    my_qsort(arr, sz, sizeof(arr[0]), compare_string_func);//arr为数组首元素地址,元素类型是地址-char*
    print(arr, sz);
    return 0;
}

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值