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

为何部分C语言函数仅能通过&运算符获取地址?

函数指针赋值异常问题分析与解决

你在练习《C程序设计语言》(第二版)的函数指针示例时,遇到了一个奇怪的问题:将reva和revn函数直接赋值给函数指针fp时(fp = reva、fp = revn),指针会变成空值,导致段错误;但给这些函数名加上&运算符后(fp = &reva),赋值就正常了。而strcmp、numcmp等函数无论加不加&都能正常赋值。

核心原因:函数类型与指针类型不兼容

你的代码里存在明显的类型不匹配问题:

  • 函数指针fp的类型是int (*)(void*, void*),指向的是接收两个void*参数、返回int的函数。
  • 但reva和revn的声明是int reva(char *, char *)、int revn(char *, char *),参数类型为char*,和fp的参数类型完全不匹配。

在C语言中的规则:

  1. 直接使用函数名赋值时,会触发函数到函数指针的隐式转换,但如果源函数类型和目标指针类型不兼容,这种转换属于未定义行为——不同编译环境会有不同表现,你遇到的就是赋值后指针为空的情况。
  2. 加&显式取函数地址时,相当于直接把内存地址赋值给指针,部分编译器会跳过严格的类型检查,让地址赋值成功,但这本质上还是不符合C标准的写法,只是临时绕过了问题。

正确解决方案:统一函数与指针类型

让函数类型和指针类型完全匹配,才是符合标准的正确做法:

  1. 修改函数声明,将reva、revn、numcmp的参数改为void*:
int numcmp(void *, void *);
int reva(void *, void *);
int revn(void *, void *);
  1. 修改函数定义,在内部将void*强制转换为char*:
int numcmp(void *s1, void *s2) {
    double v1 = atof((char*)s1);
    double v2 = atof((char*)s2);
    if(v1 < v2)
        return -1;
    else if(v1 > v2)
        return 1;
    else
        return 0;
}

int reva(void *s1, void *s2) {
    return -strcmp((char*)s1, (char*)s2);
}

int revn(void *s1, void *s2) {
    return -numcmp(s1, s2);
}

修改后,所有函数的类型都和fp的类型一致,无论加不加&,赋值都会正常工作,也彻底避免了未定义行为。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 19:18:36