仅在使用vararg省略号时,函数指针“从不兼容的指针类型分配”

我知道声明一个没有参数列表的函数(或函数指针)(并且在参数列表中没有指定void ),这意味着函数(或函数指针)具有未知数量的参数。

我写了一些测试脚本来检查这种行为:

 int my_func_1() { return(0); } int my_func_2(int x) { return(x); } int my_func_3(char x, ...) { va_list va; va_start(va, x); return(va_arg(va, int)); } int (*fp)(); fp = my_func_1; printf("%d\n", fp()); fp = my_func_2; printf("%d\n", fp(33)); fp = my_func_3; printf("%d\n", fp(33, 44)); 

我在linux下的64位机器上编译了这样的:

 gcc test.c -Wextra -pedantic -std=c1x -O3 -o test 

输出是正确的:

 0 33 44 

但是我得到了这个警告: assignment from incompatible pointer type 。 为什么在使用vararg省略号时才显示此警告?

由于指针类型被认为是不完整的,因此指定完整类型不应构成“从不兼容的指针类型分配”。 此外,只要不存在vararg省略号,分配完整类型就可以在没有任何警告的情况下工作

这个问题几乎是同一个问题。 答案都是“它没有那种方式”的答案,没有明确提到标准,为什么它不会那样工作。


  • 为什么编译器会生成警告?
  • 这种行为(警告旁边)是否可靠?
  • 这种行为编译器是否具体(阅读另一个问题,看起来mingw x86_64在2011年不支持它)?
  • 这个行为平台是否具体?

见C标准的6.7.5.3:

此外,参数类型列表(如果两者都存在)应在参数数量和省略号终止符的使用中一致; 相应的参数应具有兼容的类型。 如果一个类型具有参数类型列表而另一个类型由函数声明符指定,该函数声明符不是函数定义的一部分且包含空标识符列表,则参数列表不应具有省略号终止符,并且每个参数的类型应为与应用默认参数促销产生的类型兼容。

这表示将varargs函数赋值给fp具有不兼容的类型。

另外,正如我在上面的评论中所指出的,该程序具有未定义的行为,根据定义它是不可靠的……它可能在一个平台上的一个实现的一个版本中工作但在其他版本,实现和平台中失败…甚至可能有一天工作,但不是下一个,或者在一个项目的一个部分,而不是另一个。 实际上,在某些实现中,varargs和非varargs函数的调用序列是不同的,并且当在这样的实现上运行时,您的程序可能会崩溃。