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
相关产品推荐
相关产品推荐

