关于指针的几个知识(指针数组、数组指针、函数指针等)

本篇的主要内为:

  • 指针数组
  • 数组指针
  • 函数指针
  • 函数指针数组
  • 指向函数指针数组的指针
指针数组

       指针数组,说白了就是一个数组,数组成员的数据类型为指针。
       举个栗子:

#include<stdio.h>
int main()
{
    int i = 0;
    char *p[3] = {"Hello", "World", "!"};
    for (i = 0; i < 3; i++)
    {
        printf("%s ", p[i]);
    }
    printf("\n");
    return 0;
}

       p是一个数组,这个数组的每个成员的类型都为指针。p[0]中存储的是“Hello”的首地址,p[1]中存储的是“world”的首地址,p[2]中存储的是“!”的首地址。
这里写图片描述

数组指针

       数组指针,顾名思义就是指针,不过指针的类型却是数组。
       举个栗子:

#include<stdio.h>
int main()
{
    int a[10] = {0};
    return 0;
}

       我们知道a是一个数组,它的成员的数据类型为int,那么如果我们对进行 &a 操作。那么该用什么类型的变量来存储呢?
       这就用到了数组指针的知识。

//数组指针的定义
    int (*pa)[10] = &a;
//数组指针的理解方式:
//1.()的优先级高于[] 因此,p 先和 * 组合,表明p是一个指针变量。
//2.然后再与[]组合,表明它指向一个长度为10的数组,而数组大的每个成员的类型都为int。

       数组指针的使用:

#include<stdio.h>
int main()
{
    int a[10] = {0};
    int (*pa)[10] = &a;
    printf("a = %p\n", a);
    printf("&a = %p\n", &a);
    printf("pa = %p\n", pa);
    printf("a + 1 = %p\n", a + 1);
    printf("(&a) + 1 = %p\n", (&a) + 1);
    printf("pa + 1 = %p\n", pa + 1);
    return 0;
}

       运行结果:
              这里写图片描述
       通过上面的运行结果,我们可以看到,对数组指针 pa + 1 地址变化为 40 个。地址的变化为整个数组的大小。
数组指针在二维数组中的应用:

#include<stdio.h>
int main()
{

    int arr[3][5] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
    Print(arr);
    return 0;
}


//Print()函数的参数都可以写成什么呢?

void Print(int a[3][5], int i, int j)
void Print(int a[][5], int i, int j)
void Print(int (*a)[5], int i, int j)

       我们分析第三种情况,之前说过,我们可以把二维数组模拟成一维数组,那么二维数组的首元素就是一个数组,所以我们可以用一个数组指针来接受它,而这个一维数组的元素又有5个,所以可以创建形参为(*a)[5]

函数指针

       函数指针是指向函数的指针变量。
       首先看一段代码:

#include<stdio.h>
void fun()
{
    printf("fun\n");
}
int main()
{
    fun();
    printf("fun()  = %p\n", fun);
    printf("&fun() = %p\n", &fun);
    return 0;
}

       运行结果:
              这里写图片描述
下面这两个地址是fun函数的地址,那我们要如何将地址保存起来呢。

void (*pfun) ();

//pfun 先和 * 结合,表示是指针。
//再与()结合,表明它指向函数,函数没有参数,返回类型为void。

       函数指针的应用:

void Add(int a, int b)
{
    printf("%d\n", a + b);
}

int main()
{
    void(*p) (int, int);
    p = Add;
    (*p)(5, 3);
    return 0;
}
//    如果我们去掉解引用操作符呢?  p(5, 3)

       运行结果:
              这里写图片描述
       我们可以看到,即使不对函数指针进行解引用,我们也可以调用函数,因此,函数的调用,只需要入口地址即可。

函数指针数组

       函数指针数组,是用来存放指针类型为函数指针的数组。

#include <stdio.h>
int Add(int a, int b)
{
    return a + b;
}
int Sub(int a, int b)
{
    return a - b;
}
int Mul(int a, int b)
{
    return a - b;
}
int Div(int a, int b)
{
    return a - b;
}
int main()
{
    int i = 0;
    int(*p[4])(int, int) = {Add, Sub, Mul, Div};
    for (i = 0; i < 4; i++)
    {
        printf("%d\n", p[i](6, 2));
    }
    return 0;
}


// int(*p[4])(int, int) = {Add, Sub, Mul, Div};
// p 首先和 [] 组合,表示它是一个数组。
// 数组成员的类型是 参数为两个int型的 ,返回类型为 int 的函数的指针。

       运行结果:
              这里写图片描述

指向函数指针数组的指针

       上面说到了函数指针数组,那么对该数组取地址后,应该用什么变量存储它呢?这就用到了指向函数数组的指针。
       举个栗子:

//上面创建了一个函数指针数组,它的四个成员分别指向四个函数 Add, Sub, Mul, Div
//现在,要用变量将 &p 存储起来。
    int(*p[4])(int, int) = {Add, Sub, Mul, Div};
//pp是一个指向函数指针数组的指针
    int(*(*pp)[4])(int, int) = &p;  

       运行结果:
              这里写图片描述

以上即为本篇所有内容,不足之处还望指正。
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值