C语言学习—指针(3)

目录

一、字符指针变量

二、数组指针变量

三、二维数组传参

四、函数指针变量

五、函数指针变量的使用

六、typedef关键字

1、将 " unsigned int " 重命名

2、指针类型重命名

3、数组指针和函数指针重命名

七、函数指针数组

1、定义:

2、用途


一、字符指针变量

在指针类型中,,有一种指针是字符指针

例:

char a = 'h';
char* p = &a;

同时,字符指针还有另一种用法

例:

	const char* p = "hello world";
	printf("%s", p);

代码运行结果:

看起来是把整个字符串存放在字符指针里,其实是把首字符 ' h ' 的地址存放在该字符指针里。

而且,与字符数组不同,这样的字符串是无法修改的,所以保存这样的字符串不需要申请额外的的内存空间,即只要这样保存的常量字符串,只要常量字符串相同,存放的地址是相同的

例:

	const char* p1 = "hello world";
	const char* p2 = "hello world";
	printf("%p\n", p1);
	printf("%p\n", p2);

代码运行结果:

二、数组指针变量

与指针数组不同,指针数组是存放指针的数组,而数组指针是指向数组的指针

例:

int a[10] = {0,1,2,3,4,5,6,7,8,9};
int (*p)[10] = &a;
|     |   |
|     |   p指向数组的元素个数
|     p是数组指针变量名
p指向数组的元素类型

三、二维数组传参

因为数组名表示数组首元素地址,所以二维数组传参即把二维数组首个一维数组的地址传过去。

那么就同一维数组相同,二维数组传参也可以把形参写成指针形式

例:

#include<stdio.h>

void arr_printf_1(int (*p)[3],int x,int y)
{
	for (int i = 0; i < x; i++)
	{
		for (int j = 0; j < y; j++)
		{
			printf("%d ", *(*(p + i) + j));
		}
		printf("\n");
	}
}

void arr_printf_2(int arr[][3], int x, int y)
{
	for (int i = 0; i < x; i++)
	{
		for (int j = 0; j < y; j++)
		{
			printf("%d ", arr[i][j]);
		}
		printf("\n");
	}
}

int main()
{
	int a[3][3] = { {1,2,3},{4,5,6},{7,8,9} };
	arr_printf_1(a,3,3);
	printf("\n\n");
	arr_printf_2(a,3,3);
	return 0;
}

代码运行结果:

四、函数指针变量

既然有数组指针,那么也是有函数指针的,也就是函数也有地址

拿上面的代码为例:

#include<stdio.h>

void arr_printf_1(int (*p)[3],int x,int y)
{
	for (int i = 0; i < x; i++)
	{
		for (int j = 0; j < y; j++)
		{
			printf("%d ", *(*(p + i) + j));
		}
		printf("\n");
	}
}

int main()
{
	int a[3][3] = { {1,2,3},{4,5,6},{7,8,9} };
	printf("&arr_printf_1: %p\n", &arr_printf_1);
	return 0;
}

代码运行结果:

同时,就比如数组名是地址,函数名也是地址

	printf("&arr_printf_1: %p\n",&arr_printf_1);
	printf("arr_printf_1: %p\n", arr_printf_1);

代码运行结果:

函数指针:

void (*arr_p)(int (*p)[3],int x ,int y);
//或
void (*p)(int (*),int  ,int );
  |    |  ~~~~~~~~~~~~~~~~~~
  |    |            |
  |    |  指向函数的参数类型和个数的交代
  |    函数指针变量名
  指向函数的返回类型

五、函数指针变量的使用

继续拿上面的代码为例:

//函数指针的初始化
    void (*arr_p_1)(int(*p)[3], int x, int y) = arr_printf_1;
//或
	void (*arr_p_2)(int(*)[3], int, int) = arr_printf_1;

函数指针的调用
	arr_p_1(a, 3, 3);
	printf("\n");
//或
	(*arr_p_1)(a, 3, 3);
    printf("\n");

	arr_p_2(a, 3, 3);
	printf("\n");
//或
	(*arr_p_2)(a, 3, 3);

代码运行结果:

六、typedef关键字

typedef是⽤来类型重命名的,可以将复杂的类型,简单化。

1、将 " unsigned int " 重命名

typedef unsigned int ui;

那么定义 " unsigned int " 变量时就可以

ui a = 0;

2、指针类型重命名

typedef int* p_t;

使用:

p_t p = &a;

3、数组指针和函数指针重命名

与上面重命名有些不同

继续拿上面的代码为例:

//数组指针,新的类型名必须在*的右边
typedef int (*arr_p)[3];
//函数指针,新的类型名必须在*的右边
typedef void (*fc_p)(arr_p,int,int); 

使用:

#include<stdio.h>

//数组指针,新的类型名必须在*的右边 
typedef int(*arr_p)[3];

//函数指针,新的类型名必须在*的右边 
typedef void (*fc_p)(arr_p, int, int);//

void arr_printf(arr_p p,int x,int y)
{
	for (int i = 0; i < x; i++)
	{
		for (int j = 0; j < y; j++)
		{
			printf("%d ", *(*(p + i) + j));
		}
		printf("\n");
	}
}

int main()
{
	int a[3][3] = { {1,2,3},{4,5,6},{7,8,9} };
	fc_p arr_p = arr_printf;
	arr_p(a, 3, 3);
	printf("\n");
	return 0;
}

代码运行结果:

七、函数指针数组

也就是把指针数组和函数指针结合一下

1、定义:

int (*arr_p[10])()

2、用途

转移表,例:计算器的⼀般实现

#include<stdio.h>

void menu()
{
	printf("==============================\n");
	printf("------------1.加--------------\n");
	printf("------------2.减--------------\n");
	printf("------------3.乘--------------\n");
	printf("------------4.除--------------\n");
	printf("------------0.退出------------\n");
	printf("==============================\n");
}

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 choose = 0;
	int (*calculator[5])(int, int) = { 0,add,sub,mul,div };
	do
	{
		int x = 0, y = 0;
		menu();
		printf("请选择:");
		scanf("%d", &choose);
		if (choose)
		{
			printf("请输入:");
			scanf("%d %d", &x, &y);
			int ans = calculator[choose](x, y);
			printf("%d\n", ans);
		}
	} while (choose);
	return 0;
}
  • 4
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值