【发布时间】:2016-02-06 20:47:19
【问题描述】:
在 P.J. 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
这似乎将NULL 在 C++ 中定义为 0,在 C 中定义为 ((void *)0)。是真的,还是被定义为 __null?
如果是这样,为什么分配给 NULL 总是有效,即使根据 Plauger 的说法,分配给 (void*)0 是“错误的”?**
我对 C89 感兴趣**
【问题讨论】:
-
__null定义仅在 G++ 中。 -
我就是这么想的,谢谢。
-
在 C 中
NULL是((void *)0)和在 C++ 中0是正常的。哪一部分你不明白? -
@M.M Plauger 说将 NULL 分配给函数指针的部分是错误的,特别是当它被定义为 (void*)0 时。
-
一些旧的编译器,如 solaris 上的编译器,实际上确实会为这种类型的赋值发出警告,如
assignment mismatch: pointer to function(...) returning void "=" pointer to void