深入指针学习(3)

字符指针变量

字符指针是一种指针,是存放字符变量的指针。例如:char* str
下面有道题目:

#include <stdio.h>
int main()
{
	char str1[] = "hello bit.";
	char str2[] = "hello bit.";
	const char *str3 = "hello bit.";
	const char *str4 = "hello bit.";
	if (str1 == str2)
		printf("str1 and str2 are same\n");
	else
		printf("str1 and str2 are not same\n");

	if (str3 == str4)
		printf("str3 and str4 are same\n");
	else
		printf("str3 and str4 are not same\n");

	return 0;
}

在这里插入图片描述
这⾥str3和str4指向的是⼀个同⼀个常量字符串。C/C++会把常量字符串存储到单独的⼀个内存区域,
当⼏个指针指向同⼀个字符串的时候,他们实际会指向同⼀块内存。但是⽤相同的常量字符串去初始
化不同的数组的时候就会开辟出不同的内存块。所以str1和str2不同,str3和str4相同。

数组指针变量

指针数组是⼀种数组,数组中存放的是地址(指针)。 例如:int (*arr)[10]

数组指针变量怎么初始化
int arr[10]={0};
int (*arr)[10]=&arr;

二维数组传参的本质

⼆维数组起始可以看做是每个元素是⼀维数组的数组,也就是⼆维数组的每个元素是⼀个⼀维数组。那么⼆维数组的⾸元素就是第一行,是个⼀维数组。所以,根据数组名是数组⾸元素的地址这个规则,⼆维数组的数组名表⽰的就是第一行的地址,是⼀维数组的地址。那就意味着⼆维数组传参本质上也是传递了地址,传递的是第一行这个⼀维数组的地址,由此我们可以得到代码:

#include <stdio.h>
void test(int(*p)[5], int r, int c)
{
	int i = 0;
	int j = 0;
	for (i = 0; i<r; i++)
	{
		for (j = 0; j<c; j++)
		{
			printf("%d ", *(*(p + i) + j));
		}
		printf("\n");
	}
}
int main()
{
	int arr[3][5] = { { 1, 2, 3, 4, 5 }, { 2, 3, 4, 5, 6 }, { 3, 4, 5, 6, 7 } };
	test(arr, 3, 5);
	return 0;
}

函数指针变量

函数指针变量的创建

函数指针变量应该是⽤来存放函数地址的,未来通过地址能够调⽤函数的。

int (*pf)(int x,int y)

函数指针变量的使用

例如我们要写一个加法的函数代码:

#include <stdio.h>
int Add(int x, int y)
{
	return x + y;
}
int main()
{
	int(*pf3)(int, int) = Add;
	printf("%d\n", (*pf3)(2, 3));
	printf("%d\n", pf3(3, 5));
	return 0;
}

在这里插入图片描述

两段有趣的代码

代码一:
(*(void (*)())0)();
代码二:
void(*signal(int,void(*)(int)))(int);

代码一:从内往外看,首先void(*)()是一个函数指针,接着外面加个*,即(*(void(*)()))是将一个数强制类型转化为函数指针。
代码二:首先signal函数有两个参数分别为int和void(*)(int)的函数指针,该函数指针指向的函数参数是int,返回类型是void。

typedef关键字

typedef 是⽤来类型重命名的,可以将复杂的类型,简单化。
⽐如,你觉得 unsigned int 写起来不⽅便,如果能写成 uint 就⽅便多了,那么我们可以使⽤:

typedef unsigned int uint;

由此,我们可以将过程的代码二进行简化:

typedef void(*pfun_t)(int);
pfun_t signal(int,pfun_t);

函数指针数组

把函数的地址存到⼀个数组中,那这个数组就叫函数指针数组。例如:int (*arr[10])()

转移表

函数指针数组的应用:转移表。例如:

#include <stdio.h>
int add(int a, int b)
{
	return a + b;
}
int sub(int a, int b)
{
	return a - b;
}
int mul(int a, int b)
{
	return a*b;
}
int div(int a, int b)
{
	return a / b;
}
int main()
{
	int x, y;
	int input = 1;
	int ret = 0;
	int(*p[5])(int x, int y) = { 0, add, sub, mul, div }; //转移表
	do
	{
		printf("*************************\n");
		printf("*****  1:add  2:sub *****\n");
		printf("*****  3:mul  4:div *****\n");
		printf("*****  0:exit       *****\n");
		printf("*************************\n");
		printf("请选择:");
		scanf("%d", &input);
		if ((input <= 4 && input >= 1))
		{
			printf("输入操作数:");
			scanf("%d %d", &x, &y);
			ret = (*p[input])(x, y);
			printf("ret = %d\n", ret);
		}
		else if (input == 0)
		{
			printf("退出计算器\n");
		}
		else
		{
			printf("输⼊有误\n");
		}
	} while (input);
	return 0;
}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值