0
点赞
收藏
分享

微信扫一扫

【校招 --阶段一 高级编程语言】语言基础之指针进阶

DT_M 2022-01-20 阅读 25

一、函数指针
先看一段代码:

#include <stdio.h>
void test()
{
printf("hehe\n");
}
int main()
{
printf("%p\n", test);
printf("%p\n", &test);
return 0;
}

结果如下:
在这里插入图片描述

输出的是两个地址,这两个地址是test 函数的地址。 那我们的函数的地址要想保存起来,怎么保存?
下面我们看代码:

void test()
{
printf("hehe\n");
}
//下面pfun1和pfun2哪个有能力存放test函数的地址?
void (*pfun1)();
void *pfun2();

首先,能给存储地址,就要求pfun1或者pfun2是指针,那哪个是指针? 答案是:

#include <stdio.h>
int Add(int a, int b) {
	return a + b;
}
int main()
{
	printf("%d\n", Add(2,3));

	return 0;
}

看上边代码以前调用函数就是函数名(实参列表)。但是还可以用指针调用。
改写上边的代码:

#include <stdio.h>
int Add(int a, int b) {
	return a + b;
}
int main()
{
	printf("%d\n", Add(2,3));
	int (*p)(int, int) = Add;
	printf("%d\n", (*p)(20, 30));
}

Add是函数代码快的首地址,让指针p指向该函数的首地址。指针调用函数也能完成功能。
在这里插入图片描述
对于函数Add其函数名代表的是函数的起始地址和&Add函数地址两者等价

二、 函数指针数组

数组是一个存放相同类型数据的存储空间,那我们已经学习了指针数组, 比如:

那要把函数的地址存到一个数组中,那这个数组就叫函数指针数组,那函数指针的数组如何定义呢?

int (*parr1[10])();


答案是:parr1 parr1 先和[] 结合,说明parr1是数组,数组的内容是什么呢? 是int (*)() 类型的函数指针。

函数指针数组的用途:转移表
基于函数指针的简易计算器:

#include <stdio.h>
#include<iostream>
using namespace std;

#pragma warning(disable:4996)
int Add(int a, int b) {

	return  a + b;
}
int Mul(int a, int b) {

	return  a - b;
}
int Ch(int a, int b) {

	return  a * b;
}
int Div(int a, int b) {

	return  a / b;
}
void mun() {

	cout << "***************" << endl;
	cout << "1 加法  2 减法 " << endl;
	cout << "3 乘法  4 除法 " << endl;
	cout << "***************" << endl;
}
int main() {
	int i;
	int (*p[5])(int, int) = { NULL,Add,Mul ,Ch,Div };//将函数指针数组中的每个函数指针指向四个函数。
	int b, c;
	while (1) {
		mun();
		cout << "输入运算种类" << endl;
		cin >> i;
		cout << "输入操作数" << endl;
		cin >> b >> c;
		int a = p[i](b, c);
		cout << "答案:" << a << endl;

	}
	return 0;
}

三、函数指针 数组指针
指向函数指针数组的指针是一个指针 指针指向一个数组,数组的元素都是函数指针;
如何定义?

void test(const char* str)
{
printf("%s\n", str);
}
int main()
{
//函数指针pfun
void (*pfun)(const char*) = test;
//函数指针的数组pfunArr
void (*pfunArr[5])(const char* str);
pfunArr[0] = test;
//指向函数指针数组pfunArr的指针ppfunArr
void (*(*ppfunArr)[10])(const char*) = &pfunArr;
return 0;
}

四、回调函数

简单看一下qsort参数

参数4是一个函数指针,qsort是一个无类型排序,要排序数组的类型由用户决定,计算机无需知道类型,只需用户实现比较大小的compar函数,函数qsort只需根据函数返回值来排序。

#include<iostream>
using namespace std;
int comint(const void* qa,const void *qb) {
	int* a = (int*)qa;
	int* b = (int*)qb;
	if (*a > *b) {
		return 1;
	}else if (*a < *b) {
		return -1;
	}
	else {
		return 0;
	}
	

}
int main() {
	int arr[] = { 100,4,8,1,0,2,41,5,4,5,74,52,4,5,45,4,5,4,55,78,74 };
	int num = sizeof(arr) / sizeof(arr[0]);
	qsort(arr, num, sizeof(int), comint);
	return 0;
}

这是对int数组进行排序,用户只需对int类型数据比较大小,并返回相应的数据

int comchar(const void* qa, const void* qb) {

	char* s = *(char**)qa;
	char *ss= *(char**)qb;//取字符串的地址
	return strcmp(s, ss);
}
int main() {
	const char* arr[] = { "abcfg","jdisai","gdhsahuj","jkhjh" };
	int num = sizeof(arr) / sizeof(arr[0]);
	qsort(arr, num, sizeof(char*), comchar);

}

在对字符串数组排序时,compare是获取对应字符串的地址,只要交换他们的地址就行并不需要交换内容。

使用回调函数,模拟实现qsort(采用冒泡的方式)。

int comchar(const void* qa, const void* qb) {

	char* s = *(char**)qa;
	char *ss= *(char**)qb;//取字符串的地址
	return strcmp(s, ss);
}
void Swap( char* a, char* b,int size) {

	while (size) {
	
		char temp = *a;
		*a = *b;
		temp = *b;
		size--;
		a++;
		b++;
	}
}
void my_qsort(void* base, size_t num, size_t size, int (*compar)(const void*, const void*)) {
	assert(base != NULL);
	char* e = (char*)base;
	for (int i = 0;i < num - 1;i++) {
		int flag = 0;
		for (int j = 0;j < num - 1 - i;j++) {
			
			if (comchar(e + j * size, e + j * size + size)>0) {
				flag = 1;
				Swap(e + j * size, e + j * size + size,size);
			}
			
			
		}
		if (flag == 0) {
			break;
		}
	}


}
int main() {
	const char* arr[] = { "abcfg","jdisai","gdhsahuj","jkhjh" };
	int num = sizeof(arr) / sizeof(arr[0]);
	my_qsort(arr, num, sizeof(char*), comchar);

}
举报

相关推荐

0 条评论