C语言指针(函数指针实战)

1、函数指针实战

1.1、用函数指针调用执行函数
用函数指针指向不同的函数来实现同一个调用执行不同的结果

#include <stdio.h>

int add(int a, int b);
int sub(int a, int b);
int multiply(int a, int b);
int divide(int a, int b);

// 定义了一个类型pFunc,这个函数指针类型指向一种特定参数列表和返回值的函数
typedef int (*pFunc)(int, int);


int main(void)
{
	pFunc p1 = NULL;
	char c = 0;
	int a = 0, b = 0, result = 0;
	
	printf("请输入要操作的2个整数:\n");
	scanf("%d %d", &a, &b);
	
	printf("请输入操作类型:+ | - | * | /\n");
	
	do 
	{
		scanf("%c", &c);
	}while (c == '\n');
 
	switch (c)
	{
	case '+':
		p1 = add; break;
	case '-':
		p1 = sub; break;
	case '*':
		p1 = multiply; break;
	case '/':
		p1 = divide; break;
	default:
		p1 = NULL;	break;
	}
	
	
	result = p1(a, b);
	printf("%d %c %d = %d.\n", a, c, b, result);
	
	return 0;
}





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

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

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

int divide(int a, int b)
{
	return a / b;
}

1.2、用结构体内嵌函数指针实现分层
主题:结构体内嵌函数指针实现分层
(1)程序分层——复杂程序的设计
(2)本程序要完成一个计算器,设计了2个层次:上层为framework.c,实现应用程序框架;下层为cal.c,实现计算器。实际工作时cal.c是直接完成巩固走的,但是cal.c的关键部分是调用framework.c中的函数来完成的。
(3)先写framework.c,由一个完成,这个人在framework.c中需要完成计算器的业务逻辑,并且将相对应的接口写在对应的头文件中发出来,将来别的层次的人用这个头文件来协同工作。
(4)另一个人来完成cal.c,实现具体的计算器,这个人需要framework层的工作人员来提供头文件,但是不需要framework.c文件。
(5) 上层代码注重业务逻辑,与我们最终的目标直接关联,而没有具体干活的函数。
(6)下层代码核心就是一个结构体变量(譬如本题中的struct cal_t)的逻辑:第一步先定义结构体变量;第二部填充结构体变量;第三步调用上层写好的接口函数,把结构体变量传给它即可。

//cal.h头文件

#ifndef __CAL_H__
#define __CAL_H__

typedef int (*pFunc)(int, int);

// 结构体是用来做计算器的,计算器工作时需要计算原材料
struct cal_t
{
	int a;
	int b;
	pFunc p;
};

// 函数原型声明
int calculator(const struct cal_t *p);

#endif



//franmework.c文件
#include "cal.h"

// framework.c中应该写实际业务关联的代码

// 计算器函数
int calculator(const struct cal_t *p)
{
	return p->p(p->a, p->b);
}


//cal.c文件
#include "cal.h"
#include <stdio.h>


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

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

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

int divide(int a, int b)
{
	return a / b;
}


int main(void)
{
	int ret = 0;
	struct cal_t myCal;
	
	myCal.a = 12;
	myCal.b = 4;
	myCal.p = divide;
	
	ret = calculator(&myCal);
	printf("ret = %d.\n", ret);
	
	return 0;
}

1.3.再论typedef

1.3.1、C语言的2种类型:内建类型与用户自定义类型
(1)内建类型ADT、自定义类型UDT
1.3.2、typedef定义(或者叫重命名)类型而不是变量
(1)类型是一个数据模板,变量是一个实在的数据。类型是不占内存的,而变量是占内存的。
(2)面向对象的语言中:类型就是类class,变量就是对象。
1.3.3、typedef与#define宏的区别
typedef char *pChar;
#define pChar char *

1.3.4、typedef与结构体
(1)结构体在使用时都是先定义结构体类型,再用结构体类型去定义变量。
(2)C语言语法规定,结构体类型使用时必须是struct 结构体类型名 结构体变量名;这样的方式来定义变量。
(3)使用typedef一次定义2个类型,分别是结构体变量类型,和结构体变量指针类型。
练习题目:结构体的使用

#include <stdio.h>

// 结构体类型的定义
/*
struct student
{
	char name[20];
	int age;
};
*/

// 定义了一个结构体类型,这个类型有2个名字:第一个名字是struct student,第二个类型名叫student_t
/*
typedef struct student
{
	char name[20];
	int age;
}student_t;
*/

// 第一个类型名:struct student,第二个类型名是student
typedef struct student
{
	char name[20];
	int age;
}student;


// 我们一次定义了2个类型:
// 第一个是结构体类型,有2个名字:struct teacher,teacher
// 第二个是结构体指针类型,有2个名字:struct teacher *, pTeacher
typedef struct teacher
{
	char name[20];
	int age;
	int mager;
}teacher, *pTeacher;

typedef int *PINT;
typedef const int *CPINT;

// const int *p和int *const p是不同的。前者是p指向的变量是const,后者是p本身const

int main(void)
{
	int a = 23;
	int b = 11;

	CPINT p = &a;
	*p = 33;				// error: assignment of read-only location ‘*p’
	p = &b;

/*	
	PINT const p = &a;
	
	*p = 33;
	p = &b;					// error: assignment of read-only variable ‘p’
*/
/*	
	PINT p1 = &a;
	
	const PINT p2 = &a;		// const int *p2;	或者 int *const p2;
	*p2 = 33;
	printf("*p2 = %d.\n", *p2);
	
	p2 = &b;				// error: assignment of read-only variable ‘p2’
*/	
	
	/*
	teacher t1;
	t1.age = 23;
	pTeacher p1 = &t1;
	printf("teacher age = %d.\n", p1->age);
	
	
	struct student *pS1;		// 结构体指针
	student *pS2;				// 同上
*/	
	/*
	struct student s1;			// struct student是类型;s1是变量
	s1.age = 12;
	
	student s2;
*/	
	
	return 0;
}

1.3.5、typedef与const

(1)typedef int *PINT;	const PINT p2; 相当于是int *const p2;
(2)typedef int *PINT;	PINT const p2; 相当于是int *const p2;
(3)如果确实想得到const int *p;这种效果,只能typedef const int *CPINT; CPINT p1;

1.3.6、使用typedef的重要意义(2个:简化类型、创造平台无关类型)
(1)简化类型的描述。

char *(*)(char *, char *);		typedef char *(*pFunc)(char *, char *);	

(2)很多编程体系下,人们倾向于不使用int、double等C语言内建类型,因为这些类型本身和平台是相关的(譬如int在16位机器上是16位的,在32位机器上就是32位的)。为了解决这个问题,很多程序使用自定义的中间类型来做缓冲。譬如linux内核中大量使用了这种技术.
内核中先定义:typedef int size_t; 然后在特定的编码需要下用size_t来替代int(譬如可能还有typedef int len_t)
(3)STM32的库中全部使用了自定义类型,譬如typedef volatile unsigned int vu32;

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值