玩转指针(3)

一、字符指针变量

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

①将字符类型地址赋值给字符指针变量
c 复制代码
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)也有地址,那么函数有地址吗?答案是有的。函数的地址是存放在函数指针变量中的。&(函数名)与函数名均表示函数的地址,两者没有区别。 这点与数组不同:&(数组名)表示取出整个数组的地址,数组名表示数组首元素的地址。

② 函数指针变量的创建

函数指针变量是用来存放函数的地址
c 复制代码
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*)重新命名,将复杂类型的名字简单化。
c 复制代码
//比如觉得unsigned int这个类型比较复杂,那么就可以使用typedef将该类型重命名为unit 
typedef unsigned int unit;
int main()
{
	unsigned int a = 1;//等价于unit a=1;
	return 0;
}

②typedef关键字的使用

c 复制代码
typedef int* ptr_t;
int main()
{
	ptr_t a;//等价于int* a;
	return 0;
}

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

a.typedef在重命名数组指针类型
c 复制代码
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重命名函数指针类型
c 复制代码
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;
}

六、函数指针数组

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

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

先写出函数指针变量,然后对函数指针变量进行使当的修改,就是函数指针数组。
c 复制代码
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;
}

③函数指针数组的使用

c 复制代码
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;
}

七、转移表

c 复制代码
/*设计一个简单的计算器,实现整数的加减乘除*/
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;
}
相关推荐
叫我阿笑就好了10 分钟前
C语言扫盲
c语言·开发语言
用手码出世界1 小时前
C/C++内存管理
c语言·c++
悲伤小伞1 小时前
C/C++—有关日期类的OJ题
c语言·数据结构·c++·笔记·算法
boldht3 小时前
嵌入式项目:STM32平衡车详解 (基础知识篇) (基于STM32F103C8T6)
c语言·stm32·单片机·嵌入式硬件·嵌入式项目·单片机平衡小车
小菜鸟学代码··3 小时前
c语言常量变量
c语言·开发语言
清风浅醉3 小时前
和GPT讨论ZNS的问题(无修改)
c语言·gpt
米饭「」4 小时前
C语言内存函数
c语言·开发语言
zxctsclrjjjcph4 小时前
【C语言】函数
c语言·开发语言
全栈若城5 小时前
AI驱动TDSQL-C Serverless 数据库技术实战营-融合智能体与TDSQL-C技术,高效实现二手房数据查询与分析应用
c语言·人工智能·serverless·腾讯云tdsql-c