C语言指针

本文介绍了C语言中不同类型的指针概念,包括整型数组、指针数组、数组指针、函数指针、函数指针数组的定义和使用。通过实例展示了如何声明、赋值和调用函数指针,以及如何利用函数指针实现简单的计算器功能。同时提到了void*指针的特性,它是无类型指针,可以指向任何类型的地址,但无法进行解引用或加减运算操作。
摘要由CSDN通过智能技术生成

1、整型数组—存放整型数据的数组

int arr[10];

2、指针数组—存放指针的数组

int* arr1[10];

3、数组指针—指向一个数组的指针
怎么判断是数组指针:看p1和谁先结合,如果是
(* p1)[ ],那么最终是指针,如果*p1[ ],那么p1先和[ ]结合,最终就是数组。

int(*p1)[10] = &arr;//指向整型数组的指针
int* (*p11)[10] = &arr1;//指向指针数组的指针

4、函数指针—指向一个函数的指针

int Add(int x, int y)
{
	return x + y;
}
int main()
{
	int a = 10;
	int b = 20;
	int(*p3)(int, int) = Add;
	//首先p3和*先结合,最后这是一个指针,后面的(int,int)是函数传入参数的类型,前面int是返回类型。
	//(*p3)和函数Add有一样的作用。
	printf("%d\r\n", p3(a, b));
	printf("%d\r\n", Add(a, b));
	printf("%d\r\n", (*p3)(a, b)); 
	// 对于函数指针调用时,加不加*都可以,p3本身就指的是Add,但是加*的话必须有括号(*p3)。
	return 0;
}

练习:分析下面代码

( * ( void ( * ) ( ) ) 0 )( )
//void ( * ) ( )是函数指针类型,然后把这个类型放在括号里面再放在0前面,( void ( * ) ( ) ) 0 :就是把0强制类型转换,转换成某函数的地址;
//* ( void ( * ) ( ) ) 0 前面加*就是去找这个函数;
//( * ( void ( * ) ( ) ) 0 )( )就是调用这个函数,函数类型是无参的所以最后括号不用写参数类型。

void(*signal(int, void(*)(int)))(int)
// void(*)(int)是一个函数指针类型,signal这是函数名,(int,void(*)(int))这是函数的两个参数类型;
// 去掉函数后剩下void(* )(int)还是一个函数指针类型。
// 所以这是一个函数声明,按照理解应该写为void(*)(int) signal(int, void(*)(int))
// 前面void(*)(int)是返回值类型,signal是函数名,(int, void(*)(int))是两个参数。但这种写法是不对的!!!
// 使用typedef简化一下上面代码
// 例如typedef unsigned int uint;简化为uint
// 但是函数不同,不能写成typedef void(* )(int) pfun;二是要和*放在一起:typedef void(*   pfun   )(int)
typedef void(*   pfun   )(int);
pfun signal(int,pfun);//这两句合在一起就是原题的意思。

5、函数指针数组—存放函数指针的数组

int (*p4)(int, int) = Add;// 函数指针,但是只能存Add的地址。
// 需要一个数组,可以存放四个函数的地址--函数指针数组.
int (*p4arr[4])(int, int) = {Add,Sub,Mul,Div};// 这就是一个函数指针数组

函数指针数组练习:设计计算器

int Add(int x, int y)
{
	return x + y;
}
int Sub(int x, int y)
{
	return x - y;
}
int Mul(int x, int y)
{
	return x * y;
}
int Div(int x, int y)
{
	return x / y;
}
void Calc(int (*pf)(int, int))
{
	int x = 0, y = 0;
	printf("请输入两个操作数:");
	scanf_s("%d%d", &x, &y);
	printf("%d\r\n", pf(x, y));
}
int main()
{
	int input = 0;
	int x = 0, y = 0;
	printf("-------------------------\r\n");
	printf("-- 1、Add       2、Sub --\r\n");
	printf("-- 3、Mul       4、Div --\r\n");
	printf("--        0、exit     ---\r\n");
	printf("-------------------------\r\n");
	printf("请选择:>");
	scanf_s("%d", &input);
	printf("请输入两个操作数:");
	scanf_s("%d%d", &x, &y);
	
	//方法一
	if (input <= 4 && input >= 1) 
	{
		//把四个函数地址放到函数指针数组里面
		int(*pfarr[5])(int, int) = { 0, Add, Sub, Mul, Div };
		printf("%d\r\n",pfarr[input](x, y));
	}
	else if (input == 0)
	{
		printf("退出\r\n");
	}
	else
	{
		printf("输入错误!!!\r\n");
	}
	//方法2
	switch (input)
	{
	case 1:
		Calc(Add);
		break;
	case 2:
		Calc(Sub);
		break;
	case 3:
		Calc(Mul);
		break;
	case 4:
		Calc(Div);
		break;
	case 0:
		printf("退出\r\n");
		break;
	default:
		printf("输入错误\r\n");
		break;
	}
	return 0;
}

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

int (*pfarr[4])(int, int);// 函数指针数组
int (*(*ppfarr)[4])(int, int) = &pfarr;
// ppfarr 是一个数组指针,指向的数组有四个元素;
// 指向的数组的每个元素的类型是一个函数指针int (*)(int, int)

7、void * 指针–无类型指针,可指向任何类型的地址

int a = 10;
char ch = 'dd';
void* p1 = &a;
void* p2 = &ch;

p1 = 0; 会报错
void
不能进行解引用操作,无类型指针,不能判断元素字节大小
p1++; 会报错
void* 不能进行加减运算操作,无类型指针,不能判断元素字节大小

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值