这个函数指针的前向声明在C中是否有效?

Ann*_*nne 14 c function-pointers

我试图找出以下前向声明在ANSI-C中是否有效:

第一档:

extern void * fptr;   // opaque forward declaration.
int main (void) {
  fptr = NULL;        // set the function pointer to NULL
}
Run Code Online (Sandbox Code Playgroud)

第二档:

typedef int (*fptr_t)(int);
fptr_t fptr;         // real declaration of the function pointer
Run Code Online (Sandbox Code Playgroud)

对我来说,这应该是无效的,因为fptr如果用两种不同的类型声明,但既没有gcc也没有clang给出任何警告.

我会更具体地对C11标准的精确点感兴趣,这些点可以得出结论为什么它有效(或无效).


编辑:在C11标准中,6.2.7:2说:

引用同一对象或函数的所有声明都应具有兼容类型; 否则,行为未定义.

但我找不到如何判断是否void*兼容fptr_t.

Ale*_*nze 7

C99:

6.2.7兼容型和复合型

第2条:

引用同一对象或函数的所有声明都应具有兼容类型; 否则,行为未定义.

6.7.5.1指针声明符

第2条:

要使两个指针类型兼容,两者都应具有相同的限定条件,并且两者都应是兼容类型的指针.

如果不进一步深入研究标准,很容易看出,void功能不兼容.

我愿意打赌这不会改变C11.C已经隐式支持不同的代码和数据空间以及代码和数据指针的不同大小和表示很长一段时间,删除此功能并将语言限制在可用的较小机器子集中会很奇怪.因此,谨慎投票.更好的证据.


Joh*_*nck 6

不,它无效,因为基本上你将一个常规指针(NULL,void*)存储到一个实际上是一个函数指针的内存位置.您只是将其从编译器中隐藏起来,并且链接器并不关心,但是在一天结束时您有未定义的行为,因为两个指针类型不一定兼容.当然它可能适用于许多系统,但也许并非全部.

有关函数指针vs void指针的更多信息,请参见:can void*用于存储函数指针? - 虽然这与你所呈现的情况略有不同,但答案仍然相关.