数组指针和函数指针(3)(全是干货没有废话,文章非常简洁)

本文详细解释了字符指针、数组指针(包括一维和二维数组指针的初始化与使用)、以及函数指针的创建、使用和typedef重命名。还介绍了如何使用函数指针数组来存储和调用函数。

1.字符指针变量

在指针的类型中我们知道有一种指针类型为字符指针 char*。

char ch='w';
char*p=&ch;
*p='a';

还可以这样使用:

const char*pstr="hello world";//这里hello world都放到pstr里面了吗?
printf("%s",pstr);

这里hello world\0全部存到pstr里了吗? 

在这里并不是把hello world\0都存放到pstr里,而是把首元素h地址放到pstr里。

 

1.在这里可以把"hello world\0"看成一个字符串数组,但是这个数组不能修改。
2.当字符串常量单独放出来,得到的是首字母地址。
3.当字符串常量放到不同指针里,其首字母地址相同。

2.数组指针变量 

2.1什么是数组指针

数组指针,就是指针,存放的是数组地址。

1.int* p[4]是指针数组;对于这个代码,p和[4]相结合,说明这是一个数组,其元素为int*。
2.int(*p)[4]是数组指针;对于这个代码,p和*先结合,说明p是一个指针,指向的是int [4]的数组。

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

数组指针的初始化:

int arr[4]={1,2,3,4};
int (*p)[4]=&arr;//注意这里取得是整个数组的地址,因为数组指针指向的是整个数组。

其中p和&arr类型相同。、

 3.二维数组传参的本质 

对于二维数组而言,其数组名arr表示的是第一行地址,是一维数组的地址。第一行数组指针类型是int(*)[3]。

#include<stdio.h>
void size(int Arr[][3])
{
     int a=sizeof(*Arr);
     printf("%d",a);


}

int main()
{
     int arr[2][3]={{1,2,3},{4,5,6}};

     size(arr);

     return 0;
}

 通过监视发现Arr是int[3]*形的指针,它的地址也是arr数组第一行的地址。

通过计算发现对Arr接收的地址,解引用算出的大小为12字节,恰好是arr数组一行的大小。

通过数组指针,我们可以模拟实现二维数组:

#include<stdio.h>
void print(int Arr[][3])
{
    for(int i=0;i<2;i++)
      {
          for(int j=0;j<3;j++)
             { 
                 printf("%d  ",Arr[i][j]);
             }
           printf("\n");

      }

}

int main()
{
     int arr[2][3]={{1,2,3},{4,5,6}};

     print(&arr);

     return 0;
}

 在代码中Arr[i][j],也可以写成*(*(Arr+i)+j)的形式。因为Arr是第一行元素地址,Arr+i是不同行的地址,解引用后得到一整行的数组,而对*(Arr+i)+j而言,*(Arr+i)相当于数组名加j,相当于一行数组的首元素地址加整数,得到的是这一行中某个元素地址,再解引用,就得到这个元素的内容。

4.函数指针 

4.1函数指针的创建 

首先我们要知道:

int Add(int x,int y);
Add;
&Add;

print 和&print都是函数的地址。 

我们要创建一个指针指向函数,就需要函数指针:

int Add(int x,int y)
{
    return x+y;

}


int (*p)(int,int)=Add;
int (*p)(int,int)=&Add;

上面两种写法都是正确的,首先*和指针名结合,前面指针类型和函数返回值类型相同,后面括号内参数类型,与函数类型一致,而后指针指向对象是函数的地址。(print和&print都代表函数地址)

4.2函数指针的使用 

我们使用函数时,可以直接调用函数如Add(3,3);当我们利用指针后想要调用函数可以如下:

 
int Add(int x,int y)
{
    return x+y;

}

int main()
{
    int (*p)(int,int)=Add;
    printf("%d",(*p)(5,5));

   return 0;
}

我们知道函数名其实是一个地址,而调用函数时,可以直接Add(3,3)形式,这里Add是一个地址,指针p表示的也是Add地址,那么我们可以p(3,3)这样调用函数指针吗?

通过代码运行结果,我们发现这样同样可以运行,因此函数指针调用,可以有两种写法:

p(3,3);
(*p)(3,3);

函数返回类型为函数指针,void (*   signal(int ,void(* )(int))  )(int);
这样一个函数signal是函数名,函数的形参是int和void(*)(int),其中把里面去掉后,属于void (*  )(int)为函数返回值,这个返回值是一个函数指针。

4.3typedef重命名

typedef可以重命名变量类型,如:typedef unsigned int uint;
同样typedef可以对函数指针重命名:
我们要重命名int (* )[4],不是typedef  int (*)[4]  pArr_t;而是typedef  int (* pArr_t)[4];

使用时直接,pArr_t  p就可以成功创建一个函数指针p,他的指针类型为int (*)[4]

 5.函数指针数组

5.1指针数组的创建

有指针数组,函数指针也是指针,那么能不能将函数指针放到数组里?

#include<stdio.h>
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[4])(int,int)={Add,Sub,Mul,Div};
      return 0;
}

对于函数指针数组的创建,我们可以类比指针数组:int* p[4],p和[4]结合说明p是一个数组,然后是一个int*形的数组。
同样对于函数指针数组,p先和[]结合,p[],它的元素类型是函数指针int(* )(int,int),所以int (* p[])(int,int)就是一个函数指针数组。 (对于符号优先性,() > [] > *)

5.2函数指针数组的使用 

我们需要使用 int (* p[4])(int,int)={Add,Sub,Mul,Div}这个函数指针数组,只需要p[0](2,3)这种形式即可调用函数指针数组,其中[]里的数是下标,与存放的函数有关,而后面()里的数值是传的参数。

 

 

评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

aaa最北边

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值