指针数组和数组指针的区分

咳咳,这个问题我在学完了整本书都还没区分开,今天看到了就提一下。

指针数组

int *p[20];
//或许写成 * p[20]更好理解

由于优先级的问题,p先和20结合,然后加上星号,所以是20个指针构成的数组

补充一下,可以这样考虑,p[]是一个数组,那么编译器要知道数组元素的类型,往前面一看,哦,是一个int指针啊,所以就是元素为指针的数组了。

数组指针

指向一个数组的指针

int (*p)[20];

首先p和星号结合形成指针,指向这个数组的第一位。

数组指针指向一个数组的时候,我们给p的赋值是整个数组的地址(&a),而不是第一个元素的地址(a)
虽然在16进制输出中我们可以看到这两个是相同的,但是呢,如果将a赋值给p,就会发生错误,因为两者的类型不一样。

——————————
10.18补充:
首先,我们再列出一些例子:
int a[][]和int **a,这些例子都可以存储一个二维数组,但是各有不同,
第一个限定了数组的长宽,第二个没有限制。
自然会想到有没有限制一列的方式?其实数组指针可以实现,只要连续的几个指针都分别指向一个数组就可以存储一个矩阵了。
在这里插入图片描述
可能有人问,不是一维数组的地址吗,为什么这里扔m就行了?因为一维数组的首地址就是m啊。

还有一种是指向二维数组的指针,int (*a)[][]
在这里插入图片描述
和上面的差不多,就是多了一个维度。

接下来是函数指针的问题,经历这么多我们也勉强有一点印象了,最后的关键字才是所指的类型,所以我们接下来谈论的是一个指向函数的指针。

用途:
比如一个函数可能用到多个函数,但是不知道是哪个,所以我们可以考虑传入参数来指定函数。
再进行一下细节的讨论:
函数的地址:即函数名。
函数指针的本质也是一个指针,所以需要在main函数中声明一个,然后可以作为参数,并且因为优先级的问题,我们需要将*和变量名括在一起。

比如我需要一个转置大小写的函数,但是我还不知道进行哪种转换:

void ToUpper(char *);//转大写
void ToLower(char *);//转小写
void Transport(char *);//大小写转置
void Dummy(char *);//不改变

void show(void(*fp)(char *), char *str);//输出函数

int main()
{
    char a[10]="abc";
    void (*pf)(char *);//函数指针,声明方式和正常指针变量相同;
    char judge;//用于输入一个指令
    switch(judge)
    {
    case 'a':
        {
            fp = ToUpper;
        }
    case 'b':
        {
            fp = ToLower;
        }
        ……
		show(fp,,a);//或者干脆每一个都写show(……,a)
		……
    }
}

案例中细节部分没有过多展示(懒得写),在变量赋值的时候,需要变量指向的函数和赋值函数类型相同(参数类型、个数和返回值类型),并且不能带括号(因为这样就不是地址了)

拓展:
typedef void (*fp)(char *),那么我们就可以将一个函数指针直接定义为fp fp_one
也就是说fp就相当于这个变量类型的重命名,有一点绕不过还是很实用的。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值