C语言修行中(8)——指针(下)

本文围绕C语言展开,介绍了函数返回指针的情况,指出指针可作为返回类型,但要注意局部变量问题。还阐述了函数指针的定义、使用,强调其可指向一类函数,以及函数指针在回调函数中的应用,即函数指针作参数实现回调。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

函数返回指针

指针本质上也是一种数据类型(就像intchar),其中存储了另外一个数据的地址,因此将一个指针作为返回类型是完全可行的。
但是,需要考虑的是,在什么情况下,我们会需要函数返回一个指针类型?

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

int Add(int a, int b)
{
    int c = a + b;
    return c;
}

int main()
{
    int x = 2, y = 4;
    int z = Add(x, y);
    printf("Sum = %d\n", z);
}

我们定义了一个加和函数Add,它从main函数中接收两个参数,并将二者求和的值返回给main
需要注意的是,就像我们之前提到的那样,这里的x,y,z都是main函数里的局部变量,而a, b 则都是Add函数中的局部变量。

并且这种函数传参的方式我们之前已经讲过,成为值传递

要将函数的传参方式改为地址传递,只需改为以下程序:

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

int Add(int* a, int* b)
{
    int c = (*a) + (*b);
    return c;
}

int main()
{
    int x = 2, y = 4;
    int z = Add(&x, &y);
    printf("Sum = %d\n", z);
}

函数返回指针

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

int* Add(int* a, int* b)
{
    int c = (*a) + (*b);
    return &c;
}

void printHello()
{
  printf("Hello\n");
}

int main()
{
    int x = 2, y = 4;
    int* ptr = Add(&x, &y);
  	// printHello();
    printf("Sum = %d\n", *ptr);
}

以上代码在测试时是正常的,但是如果在打印结果之前再多调用一个函数printHello,则会导致输出错误。
但是我们将上面的程序中的Add函数改为:

int* Add(int* a, int* b)
{
    int* c = (int*)malloc(sizeof(int));
    *c = (*a) + (*b);
    return c;
}

这样,程序就可以正常地工作了。


函数指针

函数指针的定义和使用

下面这个程序定义和使用了一个函数指针:

#include <stdio.h>

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

int main()
{
    int c;
    int (*p)(int, int);
    p = &Add;
    c = (*p)(2, 3);
    printf("%d\n", c);
}

声明函数指针的语法是:int (*p)(int, int),这条语句声明了一个接收两个整型变量作为参数,并且返回一个整型变量的函数指针。
注意函数指针可以指向一类函数,即可以说,指针p指向的类型是输入两整型,输出一整型的这一类函数,即所有满足这个签名的函数,都可以赋值给p这个函数指针。

另外,要注意指针要加括号。否则int *p(int, int),是声明一个函数名为p,接收两个整型,并返回一个整型指针的函数。

函数指针赋值:p = &Add,将函数名为Add的函数指针赋值给p。同样注意只要满足p声明时的函数签名的函数名都可以赋值给p

函数指针的使用:int c = (*p)(2, 3),先对p解引用得到函数Add,然后正常传参和返回即可。

还有一点,在为函数指针赋值时,可以不用取地址符号&,仅用函数名同样会返回正确的函数地址。与之匹配的,在调用函数的时候也不需要再解引用。这种用法更加常见。

int (*p)(int, int);
p = Add;
c = p(2, 3);

再强调一下:注意函数指针可以指向一类函数,即可以说,指针p指向的类型是输入两整型,输出一整型的这一类函数,即所有满足这个签名的函数,都可以赋值给p这个函数指针。用不同的函数签名来声明的函数指针不能指向这个函数。

如以下这些函数指针的声明都是不能指向Add函数的:

void (*p)(int, int);
int (*p)(int);
int (*p)(int, char);


函数指针的使用案例(回调函数)

回调函数的概念

这里使用函数指针的案例都围绕着这么一个概念:函数指针可以用作函数参数,而接收函数指针作为参数的这个函数,可以回调函数指针所指向的那个函数。

#include <stdio.h>

void A()
{
    printf("Hello !\n");
}

void B(void (*ptr)())
{
    ptr();
}

int main()
{
    void (*p)() = A;
    B(p);
  
		B(A);	
  
    return 0;
}

或者我们可以直接在主函数中B(A),而不需要上面那写两句先复制给p,再调用p

在上面的例程中,将函数A()的函数指针传给B()B()在函数体内直接通过传入的函数指针调用函数A(),这个过程成为回调。
这里函数指针被传入另一个函数,再被用函数指针进行回调的函数A()成为回调函数。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值