我可以在C和C++中可靠地将函数指针设置为NULL吗?

rat*_*der 17 c c++ gcc pointers g++

在PJ Plauger的书"标准C库"中,他警告将函数指针赋给NULL.

具体来说,他说:

NULL 用作几乎通用的空指针常量.您将它用作数据对象指针的值,该指针应指向程序中未声明(或分配)的数据对象.正如我在第216页提到的,宏可以具有以下任何定义0,0L或(void*)0.

最后一个定义与任何数据对象指针兼容.但是,它与函数指针兼容.这意味着你不能写

int (*pfun) (void) = NULL; /* WRONG */

翻译者可能会抱怨表达式类型与您要初始化的数据对象不兼容.

他继续说:

但是,无法保证指向void的指针与任何其他(非字符)指针具有相同的表示形式.它甚至不与函数指针兼容.这意味着您不能将NULL写为通用空指针常量.你也不能安全地将它用作参数表达式来代替任意数据对象指针.

我已经将函数指针分配NULL了很长一段时间没有任何问题,我想知道它是否不可移植.

特别:

void (*test)() = NULL =>用gcc和g ++编译好

void (*test)() = 0 =>用gcc和g ++编译好

void (*test)() = (void*)0 =>在gcc和g ++中都产生了无效的转换错误

编辑:void (*test)() = (void*)0在gcc中编译很好,我使用的文件扩展名为.cpp ...尽管Plauger说分配函数指针NULL是错误的,它仍然会编译吗?

我不明白的部分是我的stddef.h中NULL的定义:

#if defined (_STDDEF_H) || defined (__need_NULL)
#undef NULL     /* in case <stdio.h> has defined it. */
#ifdef __GNUG__
#define NULL __null
#else   /* G++ */
#ifndef __cplusplus
#define NULL ((void *)0) // this line confuses me
#else   /* C++ */
#define NULL 0
#endif  /* C++ */
#endif  /* G++ */
#endif  /* NULL not defined and <stddef.h> or need NULL.  */
#undef  __need_NULL
Run Code Online (Sandbox Code Playgroud)

这似乎NULL在C++中定义为0,在C中定义为((void*)0).它是真的,还是被定义为__null?

编辑:如果是这样,为什么一直分配NULL工作,即使根据Plauger分配给(void*)0,是"错误的"?

编辑2:我对C89感兴趣

小智 9

void (*test)() = (void*)0 =>在gcc和g ++中都产生了无效的转换错误

GCC根据文件扩展名检测语言..cc使用GCC 编译文件将调用C++编译器,而不是 C编译器.

尝试使用C源文件,你会看到这是被接受的.应该是,因为它是标准所允许的.

如果是这样,为什么一直分配给NULL工作,但是不分配给(void*)0?

NULL不允许((void*)0)在C++模式下定义.在C++模式下,必须将其定义为值为0的整数常量,或者为nullptr.可以转换为任何函数指针类型.

我能否始终在C和C++中可靠地将函数指针设置为NULL?

是的,在任何符合C或C++的实现中,这都可行.

  • @rationalcoder:看起来他犯了一个错误.它发生了. (4认同)
  • @mch [GCC手册:编译C++程序](https://gcc.gnu.org/onlinedocs/gcc/Invoking-G_002b_002b.html):"GCC识别具有这些名称的文件[.cc和前面提到的其他人]并编译它们即使您以与编译C程序相同的方式调用编译器,也可以使用C++程序(通常使用名称`gcc`)." (2认同)

oua*_*uah 7

 int (*pfun) (void) = NULL;  
Run Code Online (Sandbox Code Playgroud)

它实际上是有效的.

C的任务规则说:

(请注意,这是一个初始化,但适用与简单赋值相同类型的约束和转换.)

(C99,6.5.16.1简单赋值p1约束)"以下之一应保持:[...] - 左操作数是指针,右边是空指针常量;"

(C99,7.17p3)"宏是NULL,它扩展为实现定义的空指针常量;"

因此void *,C允许为任何指针(对象指针,函数指针或)指定空指针常量.请注意,Plauger的书在提到标准C时引用了C89,但在C89中赋值约束的措辞是相同的.