C语言中使用空参数列表函数指针的行为是否符合标准?
关于空参数列表函数指针的调用合法性问题
我见过大量C语言代码使用带空参数列表的函数指针,在返回类型相同的情况下,无需强制转换就能调用不同原型的函数,只要实参的数量和类型与被调用函数的形参列表匹配即可。
示例代码
#include <stdio.h> typedef void (*func_returning_void) (); void empty_args () { printf("empty args\n"); } void zero_args (void) { printf("zero args\n"); } void one_int_arg (int arg) { printf("one arg: %d\n", arg); } void two_string_args (const char *arg1, const char *arg2) { printf("two args: %s %s\n", arg1, arg2); } int main (void) { func_returning_void funcptr; funcptr = empty_args; funcptr(); funcptr = zero_args; funcptr(); funcptr = one_int_arg; funcptr(1); funcptr = two_string_args; funcptr("one", "two"); }
提问
只要实参的数量和类型与被调用函数的形参列表匹配,这种技术是定义良好的,还是属于未定义行为(undefined behavior)?
补充说明
我知道反过来的情况属于未定义行为,因为函数定义里的空参数列表()和(void)含义一致,即函数恰好没有参数,C标准中的描述如下:
"An empty list in a function declarator that is part of a definition of that function specifies that the function has no parameters."
对应的反例代码:
void empty_params() {} int main (void) { void (*funcptr) (int) = empty_params; // 未定义行为 funcptr(1234); }
回答
这种使用空参数列表函数指针调用不同原型函数的行为属于未定义行为,原因如下:
- 类型兼容要求:C标准明确规定,通过函数指针调用函数时,指针的类型必须与被指向函数的类型兼容。带空参数列表的函数类型(
void (*)())和带具体参数的函数类型(如void (*)(int)、void (*)(const char*, const char*))并不属于兼容类型。 - 空参数列表的本质:在函数声明(非定义)中,空参数列表
()仅表示参数数量和类型未指定,并非允许它兼容任意参数列表的函数。即使实参与被调用函数的形参匹配,这种跨类型的指针调用依然违反标准要求,触发未定义行为。 - 编译器行为的不确定性:部分编译器(如GCC)默认设置下可能允许这段代码运行,但这属于编译器的非标准扩展,并非C标准的保证。切换编译器或开启严格编译模式(如
-pedantic)时,可能会出现编译警告甚至运行时错误。
内容的提问来源于stack exchange,提问作者talentless
相关产品推荐
相关产品推荐

