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

C标准是否保障返回同类型的旧式与原型化函数指针可隐式互转?

旧式函数指针与原型化函数指针的隐式转换是否符合C标准?

咱们直接把问题拆透:你测试的这种隐式转换行为并不完全受C标准保障,其中把无原型函数指针赋值给带原型的函数指针的操作,本质上属于编译器扩展特性,而非标准要求。

先看你给出的测试代码:

// 编译无警告
typedef void RetTp;
RetTp oldfn(){};
RetTp newfn(int X){};
RetTp (*oldfnp)() = newfn;
RetTp (*newfnp)(int X) = oldfn;

先讲C标准的明确规定

根据C99、C11及后续版本的标准:

  • 允许把带原型的函数指针赋值给无原型的函数指针:无原型的函数指针(也就是RetTp (*)()这种形式)在调用时会对参数执行默认提升(比如char转int、float转double),只要原函数的参数类型经过默认提升后和调用时的实际参数匹配,后续调用就是定义良好的。所以oldfnp = newfn这一步是符合标准的。
  • 禁止把无原型的函数指针隐式转换为带原型的函数指针:标准要求,只有当两个函数指针指向的函数类型兼容时,隐式转换才合法。无原型的函数类型(RetTp ())和带参数原型的函数类型(RetTp (int))并不兼容,所以newfnp = oldfn这一步属于未定义行为——标准不保证它能正常工作,具体行为由编译器决定。

再看编译器的实际表现

GCC、Clang、TCC这些编译器为了兼容大量遗留的C旧代码,都做了扩展支持:即使是标准里定义的未定义行为,它们也会宽容地接受这种转换,并且默认不发出警告。但如果你开启严格的标准检查选项(比如gcc -std=c99 -pedantic),编译器就会针对newfnp = oldfn这一行抛出类型不兼容的警告,这才是贴合C标准要求的表现。

总结一下:你的代码能编译通过是编译器的兼容扩展在起作用,并非所有场景都受C标准保障,反向转换(旧式→原型化)的行为在标准里是未定义的。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 04:02:29