函数指针解引用时,为啥加*和不加*都可以

在C/C++中,当使用函数指针调用函数时,解引用操作符*可选的。以下详细解释原因:

1. 函数指针的自动转换

  • 函数指针在调用上下文中会自动转换为函数地址。

例如:

void func(int);      // 函数声明
void (*pfunc)(int) = func; // pfunc指向func
    • pfunc(42); // 直接调用(不加*
    • (*pfunc)(42); // 解引用后调用(加*
  • 两者完全等价,编译器会生成相同的机器码。

2. 语言标准规定

  • C/C++标准明确允许这种灵活性:
    • C99标准(§6.5.2.2):函数调用操作符()要求一个指向函数的指针作为其操作数。
    • C++标准(ISO/IEC 14882):函数名或函数指针在调用时自动转换为函数地址。
  • 因此,无论是否显式解引用,只要表达式最终是函数地址,调用就能正确执行。

3. 解引用的本质

  • 解引用函数指针(如*pfunc)得到的仍是函数地址本身,而非函数内容。
  • 这是因为函数在内存中没有“值”的概念,只有入口地址。因此:
    • pfunc → 函数地址
    • *pfunc → 仍是相同的函数地址(与**pfunc***pfunc等相同)
  • 编译器会忽略多余的*,仅关注最终地址。

4. 代码一致性示例

#include <stdio.h>

void hello()
{
    printf("hello\n");
}

/*
    函数指针在调用上下文中会自动转换为函数地址。
    解引用函数指针(*fp)得到的仍是函数地址本身,而非函数内容。这是一位函数在内存中没有“值”的概念,只有入口地址。
    所以fp是函数地址,*fp也是函数地址。编译器在处理函数指针时,会忽略多余的*,仅关注最终地址。
    因此,在使用函数指针调用时,加*和不加*均可,因为编译器会忽略解引用操作,直接使用函数地址。推荐使用fp(),更简洁,更接近普通函数用法
*/
int main()
{
    void (*fp)() = hello;
    hello();
    fp();     // 指针调用函数,不加*
    (*fp)();  // 解引用调用函数,加*
    (**fp)(); // 多次解引用调用函数,仍有效
}

输出均为:

hello
hello
hello
hello

5. 设计初衷

  • 提高代码可读性:直接使用指针名调用更简洁。
  • 兼容函数行为:使函数指针的用法接近普通函数名。
  • 历史原因:早期C语言要求显式解引用(如(*ptr)()),后为简化语法放宽限制。

总结

函数指针调用时*或不加*均可,因为编译器会忽略解引用操作,直接使用函数地址。这是语言设计的人性化体现:

  • 推荐风格:直接ptr()更简洁。
  • 显式解引用(*ptr)()可强调是指针调用,增强可读性。
    两者无性能差异,按团队规范选择即可。
### C语言中指针变量作为函数参数星号(*)不加星号的区别 当指针变量作为函数参数传递给另一个函数,是否解引用运算符`*`有着不同的含义。 如果不带星号,则意味着传递的是该指针本身。这通常用于需要改变指针本身的值的情况,比如让其指向新的内存位置。而如果带有星号,则是对指针所指向的对象进行了间接寻址操作,即访问或修改实际存储于指针目标处的数据[^2]。 具体来说,在声明形参不加星号的情况下,实参与形参之间只是简单地复制了地址值;而在声明形参了星号之后,就可以通过此指针对原始数据进行读写操作了。例如下面的例子展示了如何利用含有星号的指针来实现两个整数值得互换: ```c void swap(int *p1, int *p2){ int temp; temp = *p1; // 访问并保存*p1指向的位置中的数值 *p1 = *p2; // 将*p2指向位置的内容赋值给*p1指向的位置 *p2 = temp; // 把原先*p1指向位置的内容赋予*p2指向的位置 } ``` 这里`swap()`接收两个指向整型数据的指针,并且内部使用了解引用符号(`*`)去获取以及设置这些指针指向的具体数值[^3]。 另外需要注意的一点是在调用此类接受指针形式参数的方法,应当提供相应对象的地址而不是它们自身的值。因此对于上述例子而言,应该像这样来进行方法调用: ```c int main(){ int a = 66, b = 99; swap(&a, &b); printf("a = %d, b = %d\n", a, b); return 0; } ``` 在这个过程中,`&a` `&b` 分别给出了变量`a` `b` 的确切地址,使得可以在子程序内直接对其进行更改[^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值