You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C语言中void (**foo)(int)与void *(*foo)(int)声明是否等价?

结论

这两行C语言代码完全不等价,二者声明的标识符foo属于完全不同的类型,语义、用法、适用场景均存在本质区别。

第一行代码 void (**foo)(int) 含义

这是一个二级指针声明,逐层拆解语义:

  • foo本身是一个指针,它指向的内存单元存储的是另一个指针
  • 被指向的那个指针是函数指针,指向的函数满足:接收1个int类型的入参,返回值类型为void(无返回值)

简单来说,foo是「指向void(int)类型函数指针的指针」,使用示例:

#include <stdio.h>

// 匹配目标函数签名:入参int,返回void
void log_num(int val) {
    printf("get value: %d\n", val);
}

int main() {
    // 一级函数指针,指向log_num函数入口
    void (*func_p)(int) = log_num;
    // foo是二级指针,存储一级函数指针变量的地址
    void (**foo)(int) = &func_p;

    // 需要两次解引用拿到函数入口再调用
    (**foo)(456); 
    return 0;
}
第二行代码 void *(*foo)(int) 含义

这是一个一级函数指针声明,逐层拆解语义:

  • foo本身是一个函数指针,直接指向函数入口地址
  • 它指向的函数满足:接收1个int类型的入参,返回值类型为void*(无类型通用指针,可以指向任意类型的内存地址)

简单来说,foo是「指向void*(int)类型函数的指针」,使用示例:

#include <stdlib.h>

// 匹配目标函数签名:入参int,返回void*
void* create_buffer(int size) {
    return malloc(size);
}

int main() {
    // foo直接存储函数入口地址
    void *(*foo)(int) = create_buffer;

    // C标准允许函数指针省略显式解引用,直接把指针名当函数名调用即可
    void *buf = foo(1024); // 等价于malloc(1024),申请1024字节的内存块
    free(buf);
    return 0;
}
核心差异汇总
  • 指针层级不同:前者是二级指针,存储的是另一个指针变量的地址;后者是一级指针,直接存储函数的入口地址
  • 指向的目标类型不同:前者指向的是函数指针类型的变量,后者直接指向函数
  • 关联的函数返回值不同:前者最终调用的目标函数无返回值(void),后者指向的函数返回通用指针(void*)
  • 调用方式不同:前者需要两次解引用才能拿到函数入口完成调用,后者仅需一次解引用(甚至可以省略解引用步骤直接调用)

内容的提问来源于stack exchange,提问作者Pisers

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 04:51:21