当前位置: 首页 > article >正文

玩转指针(3)

一、字符指针变量

字符指针变量(如char* p)的两种赋值方式

①将字符类型地址赋值给字符指针变量
int main()
{
	char a = 'w';
	char* p = &a;
	*p = 'm';
	return 0;
}

②将常量字符串赋值给字符指针变量
常量字符串的介绍:用" "引起来的就是常量字符串,常量字符串存放在只读数据区,这块区域的内容是可以用的,但是不能被修改的。在这里插入图片描述
一道关于字符指针变量的面试题

在这里插入图片描述
在这里插入图片描述

二、数组指针变量

①何为数组指针变量

字符指针变量(如char * p),p中存放的是字符变量的地址,p指向的是字符;整型指针变量(如int * p),p中存放的是整型变量的地址,p指向的是整型。同理,数组指针变量存放的是数组的地址(&数组名),它指向的是数组。

在这里插入图片描述

小练习:正确书写数组指针变量

在这里插入图片描述

②数组指针变量的使用

在这里插入图片描述

但这种写法不常见,通常不会这么写

③区分指针数组与数组指针

三、二维数组传参的本质

①二维数组的数组名

二维数组的每一行可以看做是一个一维数组,即二维数组是由一维数组组成的数组。二维数组的首元素就是它的第一行,因此二维数组的数组名就是数组第一行的地址。

②二维数组中的元素在内存中是连续存放的

在这里插入图片描述

③二维数组传参

二维数组传参时,实参写数组名,形参既可以写成数组的形式(此时二维数组的行的大小可以省略),也可以写成指针的形式。
a、形参写成指针的形式

在这里插入图片描述

b、形参写成数组的形式

在这里插入图片描述

c、补充
arr[i]==*(arr+i)
arr[i][j]==* (*(arr+i)+j) 。

四、函数指针变量

①函数地址的介绍:

数组有地址,变量(如int a)也有地址,那么函数有地址吗?答案是有的。函数的地址是存放在函数指针变量中的。&(函数名)与函数名均表示函数的地址,两者没有区别。 这点与数组不同:&(数组名)表示取出整个数组的地址,数组名表示数组首元素的地址。

在这里插入图片描述

② 函数指针变量的创建

函数指针变量是用来存放函数的地址
int Add(int x, int y)
{
	return x + y;
}

int main()
{
	int(*pa)(int, int) = Add;//或者写成int(*pa)(int x,int y)=Add;
	//*表示pa是指针变量(函数指针变量),存放的是函数Add的地址。pa指向的函数的返回类型为int,函数的两个参数也是int类型
	//pa的类型是int(*)(int, int)

    //*pa表示通过pa中Add的地址,调用Add函数
	int ret1 = (*pa)(3, 5);
	printf("%d\n", ret1);//8

	//一般调用Add函数的方式
	int ret2 = Add(3, 5);//这里的Add是函数名,也就是函数的地址。pa中存放的也是函数的地址,故可以将这里的Add换成pa
	ret2 = pa(3, 5);
	return 0;
}


总结:可以通过函数名(函数的地址)来调用函数,也可以通过对函数指针变量解引用来调用函数。

五、typedef关键字

①作用

用于对变量类型(如int、int*)重新命名,将复杂类型的名字简单化。
//比如觉得unsigned int这个类型比较复杂,那么就可以使用typedef将该类型重命名为unit 
typedef unsigned int unit;
int main()
{
	unsigned int a = 1;//等价于unit a=1;
	return 0;
}

②typedef关键字的使用

typedef int* ptr_t;
int main()
{
	ptr_t a;//等价于int* a;
	return 0;
}

③typedef在重命名数组指针类型和函数指针类型时,稍微有点不同

a.typedef在重命名数组指针类型
typedef int(*parr)[5];//将数组指针类型int(*)[5]重命名为parr
//typedef int(*)[5]  parr    这种写法是错误的
int main()
{
	int arr[5] = { 0 };
	int(*p)[5] = &arr;//数组指针p的类型是int(*)[5]
	parr m = &arr;
	return 0;
}
b.typedef重命名函数指针类型
typedef int (*pf)(int, int);//将函数指针类型int (*)(int, int)重命名为pf
//typedef int (*)(int, int)  pf   这种写法是错误的

int Add(int x, int y)
{
	return x + y;
}
int main()
{
	int (*p)(int, int) = Add;//p是函数指针变量,它的类型是int (*)(int, int)
	pf p2 = Add;
	return 0;
}

六、函数指针数组

①函数指针数组是用来存放函数指针或者函数的地址。(函数指针也是用来存放函数的地址,但函数指针只能存放一个函数的地址,而函数指针数组可以存放多个相同类型函数的地址)

②函数指针数组该怎么写呢?

先写出函数指针变量,然后对函数指针变量进行使当的修改,就是函数指针数组。
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;
}
int main()
{
	int(*p)(int, int) = Add;//p是函数指针变量,p所指向的函数的返回类型是int,函数的两个参数的类型也是int
	int(* p1[4])(int, int) = { Add,Sub,Mul,Div };//p1是函数指针数组的数组名,数组有4个元素,每个元素的类型都是int(*)(int,int)
	return 0;
}

③函数指针数组的使用

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;
}

int main()
{
	int(*p1)(int, int) = Add;
	int(*p2)(int, int) = Sub;
	int(*p3)(int, int) = Mul;
	int(*p4)(int, int) = Div;
	//p1、p2、p3、p4是四个函数指针变量,分别存放四个函数的地址,比较麻烦。
	//观察到这四个函数的类型是一样的,因此可以使用函数指针数组来存放四个函数的地址
	int(*p[4])(int, int) = {Add,Sub,Mul,Div};//p是函数指针数组的数组名,数组有4个元素,每个元素都是int(*)(int,int)类型
	                      //p[0]=Add,p[1]=Sub,p[2]=Mul,p[3]=Div
	for (int i = 0; i < 4; i++)
	{
		printf("%d\n", p[i](6, 3));
	}
	return 0;
}

七、转移表

/*设计一个简单的计算器,实现整数的加减乘除*/
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 menu()
{
	printf("*****    1.Add   2.Sub   *****\n");
	printf("*****    3.Mul   4.Div   *****\n");
	printf("*****    0.exit          *****\n");
}
int main()
{
	int input = 0;
	int x = 0, y = 0, ret = 0;
	do
	{
		menu();
		printf("请选择:");
		scanf("%d", &input);
	
		int(*p[5])(int, int) = { 0,Add,Sub,Mul,Div }; //转移表
		if (input >= 1 && input <= 4)
		{
			printf("请输入两个操作数:");
			scanf("%d %d", &x, &y);
			ret = p[input](x, y);
			printf("%d\n", ret);
		}
		else if (input == 0)
		{
			printf("退出计算器\n");
		}
		else
		{
			printf("输入错误,请重新输入\n");
		}

	} while (input);


	return 0;
}

http://www.kler.cn/news/321332.html

相关文章:

  • JVM 垃圾回收算法细节
  • 第13讲 实践:设计SLAM系统
  • 工作安排 - 华为OD统一考试(E卷)
  • 深度学习—神经网络基本概念
  • md编辑器语法
  • C语言究竟是一门怎样的语言?
  • E. Alternating String
  • AWS上迁移WordPress遭遇若干问题记处理办法
  • 皮肤病检测-目标检测数据集(包括VOC格式、YOLO格式)
  • 使用离火插件yoloV8数据标注,模型训练
  • @SuppressWarnings注解
  • 著名建筑物检测与识别系统源码分享
  • Java线程池和原子性
  • 『功能项目』宠物的攻击巨型化【80】
  • 人力资源数据集分析(二)_随机森林与逻辑回归
  • JavaScript 学习
  • composer详解
  • day3 QT
  • 数据仓库-数据命名标准规范
  • Android入门
  • 【Vue】Vue3 的初始化过程
  • React Native实现推送通知
  • 免费使用!通过API将文字转换为拼音
  • 15分钟学Python 第22天 :继承与多态
  • 铨顺宏科技携RTLS+RFID技术亮相工博会!
  • Python--循环
  • 数组组成的最小数字 - 华为OD统一考试(E卷)
  • OmniAns丨OPENAIGC开发者大赛高校组AI创作力奖
  • 即插即用篇 | DenseNet卷土重来! YOLOv8 引入全新密集连接卷积网络 | ECCV 2024
  • CentOs-Stream-9 解决此系统未向授权服务器注册问题