我可以在 C 和 C++ 中可靠地将函数指针设置为 NULL 吗?
Can I reliably set a function pointer to NULL in C and C++?
在P.J。 Plauger 的书 The Standard C Library,他对将函数指针分配给 NULL 提出了警告。
具体来说,他是这样说的:
The macro NULL serves as an almost-universal null pointer constant. You use it as the value of a data-object pointer that should point to no data object declared (or allocated) in the program. As I mentioned on page 216, the macro can have any of the following definitions 0, 0L, or (void *)0.
The last definition is compatible with any data object pointer. It is not, however, compatible with a function pointer. That means you cannot write
int (*pfun) (void) = NULL; /* WRONG */
The translator may complain that the expression type is incompatible with the data object you wish to initialize.
他接着说:
...There is no guarantee, however, that a pointer to void has the same representation as any other (non-character) pointer. It isn't even assignment compatible with function pointers. That means that you can't write NULL as a universal null-pointer constant. Nor can you safely use it as an argument expression in place of an arbitrary data-object pointer.
我已经将函数指针分配给 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
这似乎是在 C++ 中将 NULL
定义为 0,在 C 中将其定义为 ((void *)0) 是真的,还是被定义为 __null?
如果是这样,为什么分配给 NULL
一直有效,即使根据 Plauger 的说法,分配给 (void*)0 是“错误的”?**
我对 C89 感兴趣**
void (*test)() = (void*)0
=> produced an invalid conversion error in both gcc and g++
GCC 根据文件扩展名检测语言。使用 GCC 编译 .cc
文件将调用 C++ 编译器,而不是 C 编译器。
尝试使用 C 源文件,您会发现它已被接受。应该是,这是标准允许的。
If so, why does assigning to NULL work all the time, but assigning to (void*)0 not?
NULL
在 C++ 模式下不允许定义为 ((void*)0)
。在 C++ 模式下,它必须定义为值为 0 的整数常量,或者定义为 nullptr
。两者都可以转换为任何函数指针类型。
Can I always reliably set a function pointer to NULL in C and C++?
是的,在任何符合标准的 C 或 C++ 实现中这都有效。
int (*pfun) (void) = NULL;
实际上是有效的。
C 的赋值规则是这样说的:
(请注意,这里是初始化,但适用与简单赋值相同类型的约束和转换。)
(C99, 6.5.16.1 Simple assignment p1 Constraints) "One of the following shall hold: [...] — the left operand is a pointer and the right is a null pointer constant;"
和
(C99, 7.17p3) "The macros are NULL which expands to an implementation-defined null pointer constant;"
因此,C 允许将空指针常量分配给任何指针(对象指针、函数指针或 void *
)。请注意,Plauger 的书在提到标准 C 时指的是 C89,但赋值的措辞C89 中的约束相同。
在P.J。 Plauger 的书 The Standard C Library,他对将函数指针分配给 NULL 提出了警告。
具体来说,他是这样说的:
The macro NULL serves as an almost-universal null pointer constant. You use it as the value of a data-object pointer that should point to no data object declared (or allocated) in the program. As I mentioned on page 216, the macro can have any of the following definitions 0, 0L, or (void *)0.
The last definition is compatible with any data object pointer. It is not, however, compatible with a function pointer. That means you cannot write
int (*pfun) (void) = NULL; /* WRONG */
The translator may complain that the expression type is incompatible with the data object you wish to initialize.
他接着说:
...There is no guarantee, however, that a pointer to void has the same representation as any other (non-character) pointer. It isn't even assignment compatible with function pointers. That means that you can't write NULL as a universal null-pointer constant. Nor can you safely use it as an argument expression in place of an arbitrary data-object pointer.
我已经将函数指针分配给 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
这似乎是在 C++ 中将 NULL
定义为 0,在 C 中将其定义为 ((void *)0) 是真的,还是被定义为 __null?
如果是这样,为什么分配给 NULL
一直有效,即使根据 Plauger 的说法,分配给 (void*)0 是“错误的”?**
我对 C89 感兴趣**
void (*test)() = (void*)0
=> produced an invalid conversion error in both gcc and g++
GCC 根据文件扩展名检测语言。使用 GCC 编译 .cc
文件将调用 C++ 编译器,而不是 C 编译器。
尝试使用 C 源文件,您会发现它已被接受。应该是,这是标准允许的。
If so, why does assigning to NULL work all the time, but assigning to (void*)0 not?
NULL
在 C++ 模式下不允许定义为 ((void*)0)
。在 C++ 模式下,它必须定义为值为 0 的整数常量,或者定义为 nullptr
。两者都可以转换为任何函数指针类型。
Can I always reliably set a function pointer to NULL in C and C++?
是的,在任何符合标准的 C 或 C++ 实现中这都有效。
int (*pfun) (void) = NULL;
实际上是有效的。
C 的赋值规则是这样说的:
(请注意,这里是初始化,但适用与简单赋值相同类型的约束和转换。)
(C99, 6.5.16.1 Simple assignment p1 Constraints) "One of the following shall hold: [...] — the left operand is a pointer and the right is a null pointer constant;"
和
(C99, 7.17p3) "The macros are NULL which expands to an implementation-defined null pointer constant;"
因此,C 允许将空指针常量分配给任何指针(对象指针、函数指针或 void *
)。请注意,Plauger 的书在提到标准 C 时指的是 C89,但赋值的措辞C89 中的约束相同。