day05(C高级)指针函数&函数指针

指针函数

概念

本质是函数,函数返回值是指针。

指针数组:本质是数组,数组中每个元素是指针。

指针数组定义格式:数据类型 *数组名[元素个数];

int *arr[3];

定义格式

数据类型 *函数名(参数列表)

{

函数体;

return 地址; //当失败时一般返回NULL

}

函数内开辟空间

案例一:
#include <stdio.h>

char *fun()
{
    char buf[32] = "hello";

    return buf;
}

int main(int argc, char const *argv[])
{
    char *p = fun();
    printf("%s\n", p);

    return 0;
}

结果未知,因为返回局部变量地址,函数调用结束后没有权限使用栈区的空间了所以结果是不可控的。如果被其他进程占用,可能会报段错误或者打印奇怪的东西。

修改:可以返回堆区的地址

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *fun()
{
    char *buf = (char *)malloc(32);
    if (NULL == buf)
    {
        printf("malloc lost!\n");
        return NULL;
    }
    strcpy(buf, "hello");

    return buf;
}

int main(int argc, char const *argv[])
{
    char *p = fun();
    if (NULL == p)
        printf("fun err!\n");
    printf("%s\n", p);

    return 0;
}

案例二:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void create_space(char *p) //p=NULL
{
    p = (char *)malloc(32); //改变p的指向,让p指向开辟的堆区
    if (NULL == p)
        printf("malloc err");

    strcpy(p, "hello");
}

int main(int argc, char const *argv[])
{
    char *q = NULL;

    create_space(q); //函数调用后,q依然指向NULL
    //因为p和 q是两个空间,改变函数内的p是不影响函数外的q
    printf("%s\n", q);

    return 0;
}

报段错误:因为q指向NULL, 函数内改变形参p的指向不会影响到q,q还是指向NULL。

修改:传递二级指针

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void create_space(char **p)  //p=&q
{
    *p = (char *)malloc(32);   //*p = *&q = q
    if (NULL == *p)
        printf("malloc err");

    strcpy(*p, "hello");
}

int main(int argc, char const *argv[])
{
    char *q = NULL;

    create_space(&q);   
    //调用函数后,q指向函数内开辟的堆区。因为函数内通过传递q的地址找到q, 让q真的指向开辟的堆区了。
    printf("%s\n", q);

    return 0;
}

进一步理解:

案例三:数组传递
#include <stdio.h>

void fun(int arr[5]) //arr类型是int *
{
    arr[0] = 100;
    printf("%ld\n", sizeof(arr));
}

int main(int argc, char const *argv[])
{
    int a[5] = {1, 2, 3, 4, 5};
    fun(a);
    printf("%d\n", a[0]);

    return 0;
}

传递数组的形式是为了让用户知道要传递的是一个数组,但本质还是传递数组的首地址,也就是传递指针。

函数指针

概念

本质是指针,指向了函数。

数组指针:本质指针,指向了数组。

数组指针定义格式:数据类型 (*指针名)[列数];

int a[2][3];

int (*p)[3]=a;

定义格式

数据类型 (*指针名)(参数列表);

函数名:函数首地址

#include <stdio.h>
int add(int a, int b) //add函数名:函数的地址
{
    return a + b;
}

int sub(int a, int b) //sub类型: int (*) (int,int)
{
    return a - b;
}

int main(int argc, char const *argv[])
{
    int (*p)(int, int); //定义了函数指针
    p = add;            //让函数指针p指向add函数

    printf("%d\n", add(1, 2)); //通过函数名直接调用函数
    printf("%d\n", p(1, 2));   //通过函数指针间接调用所指的函数

    p = sub;
    printf("%d\n", sub(1, 2)); //通过函数名直接调用函数
    printf("%d\n", p(1, 2));   //通过函数指针间接调用所指的函数

    return 0;
}

把函数指针当成参数传递给函数。

一种接口,多种方法。

#include <stdio.h>
int add(int a, int b)
{
    return a + b;
}

int sub(int a, int b)
{
    return a - b;
}

int test(int (*p)(int, int), int a, int b)  //p=add, a=1, b=2;     p=sub,a=1,b=2
{
    return p(a, b);  //add(1,2);  sub(1,2);
}

int main(int argc, char const *argv[])
{
    printf("%d\n", test(add, 1, 2));
    printf("%d\n", test(sub, 1, 2));

    return 0;
}

结构体内成员是函数指针(不常用但是看内核原码的使用可能会见到)

#include <stdio.h>
struct test
{
    int (*p)(int, int);
};

int add(int a, int b)
{
    return a + b;
}

int main(int argc, char const *argv[])
{
    struct test t;
    t.p = add;

    printf("%d\n", t.p(1, 2));

    return 0;
}

                                       函数指针数组

概念

本质是数组,数组中元素是函数指针。

格式

数据类型 (*数组名[元素个数])(形参列表);

数据类型:和函数指针指向的函数的返回值一致

形参列表:和函数指针指向的函数参数一致

赋值

int (*arr[3])(int,int) = {函数名};

#include <stdio.h>

int add(int a, int b)
{
    return a + b;
}

int sub(int a, int b)
{
    return a - b;
}

int main(int argc, char const *argv[])
{
    int (*arr[2])(int, int) = {add, sub};   //函数指针数组

    printf("%d\n", arr[0](1, 2)); //add(1,2);
    printf("%d\n", arr[1](1, 2)); //sub(1,2);

    return 0;
}

练习:

a) 一个整型数

int a;

b) 一个指向整型的指针

int *p=&a;

c)一个指向指针的指针,它指向的指针是一个指向一个整型数

int a;

int *p=&a;

in **q=&p;

d)一个有10个整型数的数组

int a[10];

e)一个有10个指针的数组,该指针是指向一个整型数的

int *arr[10];

f)一个指向有10个整型数数组的指针

int a[1][10]

int (*p)[10]=a;

或者

int arr[10];

p = &arr; //相当于升级,把列地址arr升级为行地址

g)一个指向函数的指针, 该函数有一个整型参数并返回一个整型数

int (*p)(int);

h)一个有10个指针的数组,该指针指向一个函数,该函数有一个整型参数并返回一个整型数

int (*a[10])(int);

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值