C语言之函数指针

函数指针
数组在函数中当参数传递给另一个数组进行操作时,它操作的还是原数组,原因是:如果传入的数组很大,而如果要开辟新的内存去装数组,那就对内存的占用就有点太浪费了,如果数组非常之大那就不好说了。所以数组的传递都是原数组内部的元素直接变动。
  对于二位数组,指针的用法又是不同:
  int a[3][4];
  int (*p)[4];   //*p指向的是数组的行元素的首地址    *(p+i)+j      中i为0 j为0的状态是等价的。
  函数指针:三部曲
  1、把函数copy到我们主动调用的main函数里面
  2、挖掉函数名,把函数名改成*(xxx);
     格式:
int (*p)(int a,int b); // *p[xxx]有点像
p = add;       // add函数地址
p(10,10); //函数指针的调用
  函数用指针带入值,计算出的结果与普通函数调用是相同的。
今日的难点:指向二维数组的指针定义(后面有每行长度)。
函数指针的定义和基本格式,容易漏掉的括号和参数。
以及函数的四种类型用指针时的略微不同。
来分析这样一个声明,void (*f) ( ); 虽然()的优先级高于*,但由于有括号存在,首先执行的是解引用,所以f是一个指针;接下来执行( ),表明f指向一个函数,这个函数不返回任何值。现在得出结论:f是一个指向不接受参数且不返回任何值的函数的指针,简称函数指针。
注意指向函数的指针(函数指针)指向的是函数而非普通的变量,它所指向的函数也是有特定类型的,函数的类型由它的返回值类型以及形参列表确定,和函数名无关。对函数指针初始化时可以采用相同类型函数的函数名或函数指针(当然还有零指针常量)。假如有函数void test ( ),int wrong_match (int)和函数指针void (*ptf) ( )。
以下格式是合法的:
f = test;
f = &test; 
ptf = test; 
ptf = &test; 
f = pf;
要做出解释的是test和&test都可以用来初始化函数指针。C语言规定函数名会被转换为指向这个函数的指针,除非这个函数名作为 & 操作符或sizeof操作符的操作数(注意:函数名用于sizeof的操作数是非法的)。也就是说f = test;中test被自动转换为&test,而f= &test;中已经显示使用了&test,所以test就不会再发生转换了。因此直接引用函数名等效于在函数名上应用 & 运算符,两种方法都会得到指向该函数的指针。
通过函数指针调用函数  通过函数指针调用函数可以有两种方法,直接使用函数指针或在函数指针前使用解引用运算符,如下所示:
f = test; 
ptf = test; 
f ( );  
(*f) ( );   //指针两侧的括号非常重要,表示先对f解引用,然后再调用相应的函数 
ptf ( );  
(*ptf) ( );  //括号同样不能少
以上语句都能达到调用test函数的作用。ANSI C标准将f ( )认为是(*f)( )的简写形式,并且推荐使用f ( )形式,因为它更符合函数调用的逻辑。要注意的是:如果指向函数的指针没有初始化,或者具有0值(零指针常量),那么该指针不能在函数调用中使用。只有当指针已经初始化,或被赋值后指向某个函数才能安全地用来调用函数。
函数指针实例:
输入3个学生4门科目成绩,求出平均和,并输入n查找学号n多有成绩:
#include<stdio.h>
#include<Windows.h>
int ppp(int(*p)[4]){
	int S = 0;
	for (int i = 0; i<3; i++){
		for (int j = 0; j<4; j++){
			S += *(*(p+i)+j);
		}
	}
	S /= 12;
	return S;
}

int cha(int(*p)[4], int n){
	for (int i = 0; i < 4; i++)
		{
			printf("%d ",*(*(p+n)+i));
		}
	return 0;
}

void main(){
	printf("请输入成绩(每个成绩回车):");
	int n = 0;
	int a[3][4] = { { 0 }, { 0 }, { 0 } };
	for (int i = 0; i<3; i++){
		for (int j = 0; j<4; j++){
			scanf_s(" %d", &a[i][j]);
		}
	}
	int(*p)[4];
	p = a;
	ppp(p);
	printf("总平均分为%d\n", ppp(a));
	while (1)
	{
		printf("请输入学生学号n:");
		scanf_s(" %d", &n);
		if (n < 3){
			cha(p, n);
			break;
		}
		else{
			printf("无此学生\n");
		}
	}
	Sleep(550000000000000000);
}
函数指针的4种类型实例:
#include<stdio.h>
#include<stdlib.h>
#include<Windows.h>

int add(int a,int b)
{
	int c = a + b;
	return c;
}

void wucanwufan(){
	printf("沙雕\n");

}

void youcanwufan(int a,int b){
	printf("%d,%d\n",a,b);

}

int wucanyoufang(){
	return 100;
}

void main(){
	int(*p)(int a, int b);
	p = add;
	p(10, 10);
	printf("%d\n",p(10,10));

	void (*p1)();
	p1 = wucanwufan;
	p1();

	void (*p2)(int a, int b);
	p2 = youcanwufan;
	p2(100,100);
		
	int (*p3)();
	p3 = wucanyoufang;
	p3();
	printf("%d\n",p3());

	getchar();
}
输入两个数,再输入1、2、3进行不同操作,分别比出大小和和的指针实例:
#include<stdio.h>
#include<stdlib.h>
#include<Windows.h>
int fun(int a,int b){
	return (a > b ? a : b);
}

int fun1(int a, int b){
	return (a > b ? b : a);
}

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

void main(){
	int a = 0,b =0;
	int n = 0;
	printf("请输入两个数(逗号隔开):");
	scanf_s("%d,%d",&a,&b);
	int (*p)(int a,int b);
	p = fun;

	int(*p1)(int a, int b);
	p1 = fun1;

	int(*p2)(int a, int b);
	p2 = add;

	printf("请输入一二三中一个:");
	scanf_s("%d",&n);
	switch (n)
	{
	case 1:printf("%d", p(a, b));
		break;
	case 2:printf("%d", p1(a, b));
		break;
	case 3:printf("%d",p2(a, b));
		break;
	default:
		printf("输入无效");
		break; 
	}
	Sleep(5555555555555555555);
}
C语言的实例就到这,通过这些实例还是很简单能理解这些代码的含义。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值