深入理解指针【3】

1.字符指针变量

字符指针是指向字符数据类型(char)的指针变量,基本形式如下:

char *指针变量名;

比如:

char *p

 这种定义方式表示p是一个指向字符型的指针变量。

为了使字符指针变量指向一个具体的字符或字符串数组,可以进行初始化或赋值操作。例如:

  

char s[] = "Hello,World!";
char *p = s;

指针p指向字符串s的首地址

或者:

char *p = "Hello,World!";

直接将字符串的首地址赋给指针p

这两种写法是等价的。

2.数组指针变量

2.1数组指针变量是什么?

在c语言中,数组指针变量是指向数组的指针。这种指针变量可以用来访问和操作数组元素,其定义,使用和特点如下:

定义与声明

数组指针变量的定义如下:

类型名 *指针变量名 = &数组名

其中,类型名表示 数组元素的元素类型,指针变量名是用于指向数组首元素地址的指针变量,而&数组名表示数组名对应的内存地址

例如:

int arr[10];
int *p = &arr[0];//指向整型数组的arr的指针p

在前面我们来了解:

  • 整型指针变量:int * pint;存放的是整型变量的地址, 能够指向整形数据的指针
  • 浮点型指针变量:float  * pf;存放浮点型变量的地址,能够指向浮点型数据的指针

那么数组指针变量应该是:数组的地址,能够指向数组的指针变量。

来分析下面代码:

int *p1[10];
int (*p2)[10];

下面p1,p2分别是什么?

数组指针变量

int (*p)[10];

有的小伙伴可能不太懂这里解释一下 :p先和*结合,说明p是一个指针变量变量,然后 指着指向的是一个大小为10个整型的数组。所以p是一个指针,指向一个数组,叫数组指针。

这里要注意:[]的有优先级要高于*号的,所以必须加上()来保证p先和*结合。

2.2数组指针变量怎么初始化

数组指针变量是用来存放数组地址的,那么怎么获得数组的地址呢?就是我们之前学的&数组名

int  arr[10] = {0};

&arr;//得到的就是数组的地址

如果要存放个数组的地址,就得放在数组指针变量中,如下:

int(*p)[10] = &arr; 

调试可以看出&arr和p的类型是完全一致的。

 

 3.二维数组传参的本质

以前我们有一个二维数组需要传参给一个函数的时候,我们是这样写的:

这里实参是二维数组,形参也写成二维数组的形式,这里还可以换一种写法更高效

 首先再来复习一下二维数组,在C语言中,二维数组是一种特殊的一维数组,其元素可以进一步分解为行和列,那么二维数组的首元素就是第一行,是一个一维数组。

如下图:

 二维数组的数组名表示的就是第一行的地址,是一维数组的地址。根据上⾯的例⼦,第⼀⾏的⼀维数组的类型就是 int [5] ,所以第⼀⾏的地址的类 型就是数组指针类型 int(*)[5] 。那就意味着⼆维数组传参本质上也是传递了地址,传递的是第⼀ ⾏这个⼀维数组的地址,那么形参也是可以写成指针形式的。如下:

 总结:二维数组传参,形参部分可以写成数组,也可以写成指针形式。

4.函数指针变量

在C语言中,函数指针变量是一种特殊的指针变量,它指向一个函数。这种机制允许在运行时选择要调用的函数,并且可以将函数作为参数传递给其他函数。

那么我们来做个测试看一下函数是否有地址?

示例:

输出结果:

 所以函数是有地址的,函数名就是函数的地址,当然也可以通过 &函数名 的⽅

式获得函数的地址。

如果想要将函数的地址存放起来,就待创建函数指针变量。

函数指针变量的写法其实和数组指针

⾮常类似。如下:

函数指针类型解析:

4.2函数指针变量的使用

 通过函数指针调用指针指向函数:

 运行结果:

 4.3 typedef关键字

在C语言中,typedef关键字用于为已有的数据类型定义一个新的别名,以便于代码的书写和阅读。它并不是创建一种新的数据类型,而是给一个已经存在的类型取一个新名字。这使得程序更加简洁明了,并且增强了代码的可读性和可维护性。

基本语法格式:

typedef<现有类型名><新类型名>;

例如,可以将int类型重命名为MY_TNL:

 typedef int MY_INT;

 这样,我们就可以使用MY_INT来代替int类型了。

如果我们数组指针类型int(*)[5],需要重命名为parr_t,那可以这样写:

typedef int(*parr_t)[5];//新的类型名必须在*的右边
函数指针类型的重命名也是⼀样的,⽐如,将 void(*)(int) 类型重命名为 pf_t ,就可以这样写:
typedef void(*pfun_t)(int);//新的类型名必须在*的右边

代码1:

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

那么要简化的代码1,可以这样写:

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

5.函数指针数组

数组是一个存放相同类型数据的存储空间

而函数指针数组是一种特殊的数组类型,其每个元素都是一个指向函数的指针。这种数据结构允许我们存储和管理多个函数的地址,并通过索引访问这些函数以执行相应的操作。

比如:

int *arr[10];
//数组的每个元素是int*
定义与声明
定义一个函数指针数组的基本语法如下:
类型(*数组名)[数量]:

例如,我们想定义一个指向整型函数的数组,可以这样声明:

int (*func_pttr_array)[3]

这里func_ptr_array是一个包含三个整型函数指针的数组。

那要把函数的地址存到⼀个数组中,那这个数组就叫函数指针数组,那函数指针的数组如何定义呢?
int (*parr1[3])();
int *parr2[3]();
int (*)() parr3[3]
parr1 先和 [] 结合,说明 parr1是数组,数组的内容是什么呢?
int (*)() 类型的函数指针。

6.转移表

函数指针的数组用途:转移表

举例:计算器的一般实现:

使用函数指针数组的实现: 

 

  • 13
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值