提问人:talentless 提问时间:5/26/2023 最后编辑:talentless 更新时间:6/11/2023 访问量:120
在 C [duplicate] 中使用带有空参数列表的函数指针
Using function pointers with empty parameter lists in C [duplicate]
问:
我见过很多 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");
}
只要参数的数量和类型与被调用函数的参数列表匹配,这种技术是定义明确的,还是依赖于未定义的行为?
注意:我知道反之则是未定义的行为,因为在函数定义中,空参数列表与恰好为零的参数具有相同的含义;正如 C 标准所述:()
(void)
“函数声明符中的空列表是该函数定义的一部分,它指定该函数没有参数。”
void empty_params() {}
int main (void)
{
void (*funcptr) (int) = empty_params; // UB
funcptr(1234);
}
答:
2018 年标准中适用的段落是 6.5.2.2 6,因为它以“如果表示被调用函数的表达式具有不包含原型的类型”开头。(原型是函数的声明,用于声明其参数的类型。所以不包括原型。预计这将在 2023 年标准中发生变化,该标准取消了对没有原型的函数声明的支持。 因为函数声明将变得与 相同。typedef void (*func_returning_void) ();
()
(void)
关于调用用原型定义的函数,这一段说:
...对每个参数执行整数升级,并且具有 type 的参数将提升为 。这些称为默认参数升级。如果参数数不等于参数数,则行为未定义。如果函数是使用包含原型的类型定义的,并且原型以省略号 () 结尾,或者升级后的参数类型与参数的类型不兼容,则行为是未定义的...
float
double
, ...
因此,当使用声明 with 的函数指针调用用原型定义的函数时,只要参数数与参数数匹配,参数提升后的类型兼容,并且定义不使用省略号,就可以定义行为。()
请注意,示例的行为不是由 C 标准定义的。 使用 type 的参数调用函数,而函数使用 type 的参数定义,这些参数是不兼容的类型。two_strings_args
funcptr("one", "two");
char *
const char *
评论
void
(void)