我正在用 C++ 编写代码,并使用一个在失败时返回 NULL 的 C 函数。正确的做法是什么,将其返回值与 NULL 或 nullptr 进行比较?
if ((CreateEventEx(myEventHandleHere) == NULL)
{
...
}
或者
if ((CreateEventEx(myEventHandleHere) == nullptr)
{
...
}
附录C 标准库中非规范的C++ 标准草案说:C.4
在 <clocale>、<cstddef>、<cstdio>、<cstdlib>、<cstring>、<ctime> 或 <cwchar> 中定义的宏 NULL 是本国际标准中实现定义的 C++ 空指针常量(18.2)。
相应的规范性部分同意例如18.2
说:
宏 NULL 是本国际标准 (4.10).194 中实现定义的 C++ 空指针常量
这意味着如果您使用那些特定的标头NULL
应该兼容,nullptr
然后我会使用nullptr
.
在涵盖兼容性的附录D
中似乎没有对头.h
文件做出类似的声明,因此尽管我们希望NULL
并且nullptr
应该兼容空指针常量,如果它们不是从标准的角度来看,我们会感到惊讶,它似乎至少被低估。这让我们陷入了两难境地,从实际的角度来看,我们非常确定它们是兼容的,但我们没有足够的标准信息来证明这一点。
因此,我将NULL
按照您正在使用的特定头文件的定义使用,或者我们可以使用!= 0
,因为幸运的是 C99 和 C++11 都告诉我们这0
是一个空指针常量。
从 C99 部分6.3.2.3
指针:
值为 0 的整型常量表达式或转换为 void * 类型的表达式称为空指针常量。55) 如果将空指针常量转换为指针类型,则生成的指针(称为空指针)为保证比较不等于指向任何对象或函数的指针。
和:
任何指针类型都可以转换为整数类型。除非前面指定,结果是实现定义的
和 C++ 部分的4.10
指针转换告诉我们:
空指针常量是一个整数文字 (2.14.2),其值为 0 或 std::nullptr_t 类型的纯右值。空指针常量可以转换为指针类型;结果是该类型的空指针值,并且可以与对象指针或函数指针类型的所有其他值区分开来。[...]
它们是完全等价的,所以使用nullptr
becauseNULL
是一种原始的 C 主义,没有理由再活下去了。
但是在 CreateEventEx 的情况下,你有一个有趣的好处,不是所有的 invalid HANDLE
s being nullptr
,它们中的一些是INVALID_HANDLE_VALUE
相反的。因此,在HANDLE
. 您需要准确检查 CreateEventEx 在失败时返回的内容。
我会使用NULL
,因为那是 C 使用的(也是nullptr
C++11 中的新功能,所以如果你不使用 C++11,那么你必须使用NULL
)。另一方面,您可以简单地不显式检查任何一个值,而是进行隐式比较,让编译器!= 0
为您检查:
if (CreateEventEx(myEventHandleHere))
{
...
}
您应该将该值分配给一个变量,以便以后可以释放它(如果这是 C API 所要求的):
TypeName event = CreateEventEx(myEventHandleHere);
if (event)
{
...
free event when done...
}
我不确定如果函数返回 NULL 为什么会很重要。那是一个实现细节。有许多旧的 C++ 函数返回 NULL。许多新功能将返回nullptr
。因此,如果您决定在自己的NULL
代码中从空指针值切换到nullptr
空指针值,那么您应该对此保持一致,无论该函数是否最初是用 C 编写的。当它被编译为 C++ 时,它变成了一个 C++ 函数.
然而。在这种情况下,返回类型是 a HANDLE
。实际上HANDLE
是 a 的 typedef的事实void*
是一个实现细节。WinAPI 文档说,当 aHANDLE
无效时,它与NULL
. 在这种情况下,我建议您使用 WinAPI 文档,并使用NULL
. 如果 WinAPI 不使用 typedefs,并且只是将其所有函数记录为返回,那么如果您在其余的 C++ 代码中使用,void*
我会使用。nullptr
nullptr