C++ 检查C/C+中的空指针+;

C++ 检查C/C+中的空指针+;,c++,c,if-statement,null,coding-style,C++,C,If Statement,Null,Coding Style,在最近的一次代码审查中,一名参与者试图强制以以下方式执行指针上的所有NULL检查: int * some_ptr; // ... if (some_ptr == NULL) { // Handle null-pointer error } else { // Proceed } 而不是 int * some_ptr; // ... if (some_ptr) { // Proceed } else { // Handle null-pointer error }

在最近的一次代码审查中,一名参与者试图强制以以下方式执行指针上的所有
NULL
检查:

int * some_ptr;
// ...
if (some_ptr == NULL)
{
    // Handle null-pointer error
}
else
{
    // Proceed
}
而不是

int * some_ptr;
// ...
if (some_ptr)
{
    // Proceed
}
else
{
    // Handle null-pointer error
}

我同意他的方法更清楚一点,因为它明确地说“确保这个指针不是空的”,但我要反驳这一点,我要说的是,任何处理这段代码的人都会理解,在
if
语句中使用指针变量是隐式检查
空的
。另外,我觉得第二种方法引入同类错误的可能性较小:

if (some_ptr = NULL)
这是一个绝对痛苦的发现和调试


如果(foo)
足够清楚,您更喜欢哪种方式?为什么。使用它。

我使用过的大多数编译器至少会在
if
赋值时发出警告,而不需要进一步的语法分析,所以我不相信这个参数。也就是说,我在职业上使用过这两种方法,但对这两种方法都没有偏好。在我看来,
==NULL
显然更清晰。

根据我的经验,最好使用
if(ptr)
if(!ptr)
形式的测试。它们不依赖于符号的定义
NULL
。他们不会暴露意外任务的机会。它们清晰而简洁

<强>编辑:>在注释中指出SOABOX,它们与C++类(如代码> AutoPPTR <代码> >兼容,这些对象充当指针,并提供转换为BOOL >以使这一习惯成真。对于这些对象,与

NULL
的显式比较必须调用到指针的转换,这可能有其他语义副作用,或者比
bool
转换所暗示的简单存在性检查更昂贵

我更喜欢在没有多余文本的情况下表达意思的代码
if(ptr!=NULL)
if(ptr)
具有相同的含义,但以冗余的特异性为代价。下一个合乎逻辑的事情是编写
if((ptr!=NULL)==TRUE)
,这样就产生了疯狂。C语言清楚地表明,由
if
while
等测试的布尔值具有非零值的特定含义为真,零为假。冗余并不能使它更清晰。

我使用
if(ptr)
,但这完全不值得争论

我喜欢我的方式,因为它很简洁,尽管其他人说
==NULL
使它更容易阅读和更明确。我知道他们是从哪里来的,我只是不同意额外的东西会让事情变得更容易。(我讨厌宏,所以我有偏见。)由你决定

我不同意你的论点。如果在条件中没有收到分配警告,则需要提高警告级别。就这么简单。(出于对一切美好事物的热爱,不要改变它们。)


注意,在C++0x中,如果(ptr==nullptr)
,我们可以执行
,这对我来说读起来更好。(同样,我讨厌宏。但是
nullptr
很好。)尽管如此,我仍然喜欢
if(ptr)
,因为我已经习惯了它。

实际上,我使用这两种变体

在某些情况下,首先检查指针的有效性,如果指针为NULL,则返回/退出函数。(我知道这会导致讨论“一个函数是否只有一个退出点”)


大多数情况下,检查指针,然后执行所需操作,然后解决错误情况。结果可能是丑陋的x倍缩进代码,带有多个if。

我将从以下内容开始:一致性是王道,决策不如代码库中的一致性重要

在C++中

空定义为C++中的代码> 0 >代码>或<代码> 0L>代码> <>如果你读了C++编程语言,我不确定他是否也做了比较,我读过这本书已经有一段时间了,我认为他只是做了<代码>(某个PTR)< />没有明确的比较,但是我对此很模糊。 原因是

NULL
宏具有欺骗性(几乎所有宏都是如此),它实际上是
0
文本,而不是名称所暗示的唯一类型。避免宏是C++的一般准则之一。另一方面,
0
看起来像一个整数,与指针比较或分配给指针时,它不是整数。就个人而言,我可以选择任何一种方式,但通常我会跳过明确的比较(尽管有些人不喜欢这一点,这可能就是为什么你有一位投稿人建议进行更改的原因)

不管个人感觉如何,这在很大程度上是一种选择,因为没有一种正确的方法

这是一个很清楚的习惯用法,我更喜欢它,在比较过程中不可能意外地赋值,它清楚地读到:

if (some_ptr) {}
如果您知道
some_ptr
是指针类型,这一点很清楚,但它也可能看起来像一个整数比较:

if (some_ptr != 0) {}
这很清楚,在一般情况下,这是有道理的。。。但这是一个漏洞百出的抽象,
NULL
实际上是
0
文字,很容易被误用:

if (some_ptr != NULL) {}
C++11有
nullptr
,这是现在首选的方法,因为它是显式和准确的,只是要小心意外赋值:

if (some_ptr != nullptr) {}
在您能够迁移到C++0x之前,我认为担心使用哪种方法是浪费时间的,它们都是不充分的,这就是nullptr被发明的原因(以及产生完美转发的通用编程问题)。最重要的是保持一致性

在C中 C是另一种动物

在C
NULL
中可以定义为
0
((void*)0)
,C99允许实现定义的NULL指针常量。因此,它实际上归结为实现的
NULL
定义,您必须在标准库中检查它

宏在基因中非常常见
int f(void* p)
{
    if (!p) { return -1; }

    // p is not null
    return 0;
}
if (error_condition)
  bail_or_fix();
  return if not fixed;

// If I'm still here, I'm on the happy path
if (foo == NULL)
{
    // null case
}
else
{
    // non null case
}
if (foo != NULL)
{
    // non null case
}
else
{
    // null case
}
if (ptr)

if (!ptr)
while(i--)
{
    // Something to do i times
}

while(cin >> a >> b)
{
    // Do something while you've input
}
unsigned char chx;

if (chx) // ...
if (chx == 1) // ...