C语言之复杂指针简析

指针数组和数组指针

  • 指针数组:首先它是一个数组,数组的元素都是指针,数组占多少个字节由数组本身决定。它是“储存指针的数组”的简称。
  • 数组指针:首先它是一个指针,它指向一个数组。在 32 位系统下永远是占 4 个字节,至于它指向的数组占多少字节,不知道。它是“指向数组的指针”的简称。

那么下边俩个分别叫做什么呢?
int *p1[4];
int (*p2)[4];
第一个我们称之为指针数组。“[ ]”的优先级比“”要高。p1 先与“[ ]”结合,构成一个数组的定义,数组名为 p1,int 修饰的是数组的内容,即数组的每个元素。这是一个数组,其包含 4 个指向 int 类型数据的指针,即指针数组。
我们可以这样理解:
这里写图片描述
第二个我们称之为数组指针。在这里“()”的优先级比“ []”高,“*”号和 p2 构成一个指针的定义,指针变量名为 p2,int 修饰的是数组的内容,即数组的每个元素。数组在这里并没有名字,是个匿名数组。那现在我们清楚 p2 是一个指
针,它指向一个包含 4 个 int 类型数据的数组,即数组指针。
同样,也可以这样理解:
这里写图片描述


函数指针,函数指针数组和指向函数指针数组的指针

  1. 函数指针:就是函数的指针。它是一个指针,指向一个函数。
  2. 函数指针数组:它是一个数组,数组内存储了指向函数的指针。
  3. 函数指针数组指针:它是一个指针,只不过这个指针指向一个数组,这个数组里面存的都是指向函数的指针。

    看如下例子:
    char * (pf)(char p1,char * p2);
    这个我们称之为函数指针。” * “号和 pf 构成一个指针的定义,指针变量名为 pf。pf指向一个函数,该函数的返回值类型是char * ,函数参数有两个,分别为p1和p2,p1和p2都是char * 类型.

    char * (pf[3])(char p);
    这个我们称之为 函数指针数组。“[ ]”的优先级比“*”要高。pf 先与“[ ]”结合,构成一个数组的定义,数组名为 pf。数组内存储了 3 个指向函数的指针。这些指针指向一些函数,其中函数返回值类型为指向字符的指针,参数为一个指向字符的指针。

    char * ((*pf)[3])(char p);
    这个称为 指向函数指针数组的指针。该 pf 确实是实实在在的指针。这个指针指向一个包含了 3 个元素的数组;这个数组里面存的是指向函数的指针;这些指针指向一些返回值类型为 指向字符的指针、参数为一个 指向字符的指针 的函数。

下面通过转移表了解一下函数指针数组的用法:

void menu()
{
    printf("**************************\n");
    printf("*******1.add   2.sub*****\n");
    printf("********3.mul   4.div*****\n");
    printf("****************0.exit*****\n");
    printf("请选择:");
}
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 x = 0;
    int y = 0;
    int input = 1;
    int ret = 0;
    int (*p[5])(int , int ) = { 0, Add, Sub, Mul, Div };//转移表
    do
    {
        menu();
        scanf("%d", &input);
        if (input >=1 && input <=4)
        {
            printf("输入操作数:");
            scanf("%d%d", &x, &y);
            ret = p[input](x, y);
        }
        else
        {
            printf("输入错误,请重新输入:");
        }
        printf("ret=%d\n", ret);

    } while (input);
    system("pause");
    return 0;
}

小试:
(* (void(*) ())0)();
void (* signal(int,void(*)(int)))(int);

第一个为函数调用。怎么理解呢?
首先 void (* )()是一个函数指针,该指针指向一个无参数,返回值类型为void型(即没有返回值)的函数。
(void (* )())0:就是将0强制转换成函数指针类型。
(* (void (*)())0):就是取0地址处开始的一段内存里面的内容,其内容就是保存在首地址为 0 的一段区域内的函数。
(* (void(*) ())0)():就是对函数进行调用。

第二个可以理解为:
signal是一个函数,其返回值类型为void (*) (int)型,即函数指针类型;参数有两个,分别为整形和函数指针类型。可简写为:
typedef void (*pfun_t) (int);
pfun_t signal(int , pfun_t);


回调函数:

就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,就说这是回调函数。
使用回调函数,模拟实现qsort。

int int_cmp(const void* p1, const void* p2)
{
    if (*(int *)p1 > *(int *)p2)
    {
        return 1;
    }
    else if (*(int *)p1 < *(int *)p2)
    {
        return -1;
    }
    else
    {
        return 0;
    }
}
void _swap(void *p1, void *p2, int size)
{
    int i = 0;
    for (i = 0; i < size; i++)
    {
        char tmp = *((char *)p1 + i);
      *((char *)p1 + i) = *((char *)p2 + i);
       *((char *)p2 + i)=tmp;
    }
}
void mybubble(void *base, int count, int size, int(*cmp)(void *, void*))
{
    int i = 0;
    int j = 0;
    for (i = 0; i < count - 1; i++)
    {
        for (j = 0; j < count - i - 1; j++)
        {
            if (cmp((char *)base + j*size, (char *)base + (j + 1)*size)>0)
            {
                _swap((char *)base + j*size, (char *)base + (j + 1)*size, size);
            }
        }
    }

}
int main()
{
    int a[] = { 1, 2, 2, 56, 32, 6, 8, 0 };
    char *arr[] = { "aabb", "dddd", "bbbb", "eeee" };
    int i = 0;
    mybubble(a, sizeof(a) / sizeof(a[0]), sizeof(int), int_cmp);
    for (; i < sizeof(a) / sizeof(a[0]); i++)
    {
        printf("%d ", a[i]);
    }
    printf("\n");
    system("pause");
    return 0;
}

指针概述:
这里写图片描述

猜你喜欢

转载自blog.csdn.net/mmwwxx123/article/details/80412435
今日推荐