在 C/C++ 中检查空指针
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3825668/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Checking for NULL pointer in C/C++
提问by Bryan Marble
In a recent code review, a contributor is trying to enforce that all NULL
checks on pointers be performed in the following manner:
在最近的代码中,贡献者试图强制执行所有NULL
指针检查以下列方式执行:
int * some_ptr;
// ...
if (some_ptr == NULL)
{
// Handle null-pointer error
}
else
{
// Proceed
}
instead of
代替
int * some_ptr;
// ...
if (some_ptr)
{
// Proceed
}
else
{
// Handle null-pointer error
}
I agree that his way is a little more clear in the sense that it's explicitly saying "Make sure this pointer is not NULL", but I would counter that by saying that anyone who's working on this code would understand that using a pointer variable in an if
statement is implicitly checking for NULL
. Also I feel the second method has a smaller chance of introducing a bug of the ilk:
我同意他的方式更清楚一点,因为它明确表示“确保此指针不为 NULL”,但我会反驳说,任何正在处理此代码的人都会理解在一个指针变量中使用指针变量if
语句隐式地检查NULL
. 另外我觉得第二种方法引入同类错误的可能性较小:
if (some_ptr = NULL)
which is just an absolute pain to find and debug.
这只是查找和调试的绝对痛苦。
Which way do you prefer and why?
你更喜欢哪种方式,为什么?
回答by RBerteig
In my experience, tests of the form if (ptr)
or if (!ptr)
are preferred. They do not depend on the definition of the symbol NULL
. They do not expose the opportunity for the accidental assignment. And they are clear and succinct.
根据我的经验,if (ptr)
还是if (!ptr)
首选形式的测试。它们不依赖于符号的定义NULL
。他们不会暴露意外分配的机会。而且它们清晰简洁。
Edit:As SoapBox points out in a comment, they are compatible with C++ classes such as auto_ptr
that are objects that act as pointers and which provide a conversion to bool
to enable exactly this idiom. For these objects, an explicit comparison to NULL
would have to invoke a conversion to pointer which may have other semantic side effects or be more expensive than the simple existence check that the bool
conversion implies.
编辑:正如 SoapBox 在评论中指出的那样,它们与 C++ 类兼容,例如auto_ptr
充当指针的对象,并提供转换以bool
完全启用此习语。对于这些对象,与 的显式比较NULL
必须调用到指针的转换,这可能具有其他语义副作用,或者比bool
转换暗示的简单存在检查更昂贵。
I have a preference for code that says what it means without unneeded text. if (ptr != NULL)
has the same meaning as if (ptr)
but at the cost of redundant specificity. The next logical thing is to write if ((ptr != NULL) == TRUE)
and that way lies madness. The C language is clear that a boolean tested by if
, while
or the like has a specific meaning of non-zero value is true and zero is false. Redundancy does not make it clearer.
我更喜欢能在没有不需要的文本的情况下说明含义的代码。if (ptr != NULL)
具有相同的含义,if (ptr)
但以多余的特异性为代价。下一个合乎逻辑的事情是写作,if ((ptr != NULL) == TRUE)
而那种方式就是疯狂。C 语言很清楚,由if
,while
等测试的布尔值具有特定含义,非零值为真,零值为假。冗余并没有使它更清楚。
回答by wilx
if (foo)
is clear enough. Use it.
if (foo)
够清楚了。用它。
回答by M2tM
I'll start off with this: consistency is king, the decision is less important than the consistency in your code base.
我将从这一点开始:一致性为王,决定不如代码库中的一致性重要。
In C++
在 C++ 中
NULL is defined as 0 or 0L in C++.
NULL 在 C++ 中定义为 0 或 0L。
If you've read The C++ Programming LanguageBjarne Stroustrup suggests using 0
explicitly to avoid the NULL
macro when doing assignment, I'm not sure if he did the same with comparisons, it's been a while since I read the book, I think he just did if(some_ptr)
without an explicit comparison but I am fuzzy on that.
如果你读过The C++ Programming Language Bjarne Stroustrup 建议在做赋值时0
显式使用避免NULL
宏,我不确定他是否对比较做了同样的事情,我读这本书已经有一段时间了,我想他只是做了if(some_ptr)
没有明确的比较,但我对此很模糊。
The reason for this is that the NULL
macro is deceptive (as nearly all macros are) it is actually 0
literal, not a unique type as the name suggests it might be. Avoiding macros is one of the general guidelines in C++. On the other hand, 0
looks like an integer and it is not when compared to or assigned to pointers. Personally I could go either way, but typically I skip the explicit comparison (though some people dislike this which is probably why you have a contributor suggesting a change anyway).
这样做的原因是NULL
宏具有欺骗性(几乎所有宏都是如此)它实际上是0
字面量,而不是顾名思义的唯一类型。避免使用宏是 C++ 中的一般准则之一。另一方面,0
看起来像一个整数,当与指针进行比较或分配时它不是。就我个人而言,我可以采用任何一种方式,但通常我会跳过明确的比较(尽管有些人不喜欢这一点,这可能就是为什么您有贡献者建议进行更改的原因)。
Regardless of personal feelings this is largely a choice of least evil as there isn't one right method.
不管个人感受如何,这在很大程度上是一种最不邪恶的选择,因为没有一种正确的方法。
This is clear and a common idiom and I prefer it, there is no chance of accidentally assigning a value during the comparison and it reads clearly:
这是一个清晰且常见的习惯用法,我更喜欢它,在比较过程中不会意外分配一个值,它读起来很清楚:
if(some_ptr){;}
This is clear if you know that some_ptr
is a pointer type, but it may also look like an integer comparison:
如果您知道这some_ptr
是一个指针类型,这很清楚,但它也可能看起来像一个整数比较:
if(some_ptr != 0){;}
This is clear-ish, in common cases it makes sense... But it's a leaky abstraction, NULL
is actually 0
literal and could end up being misused easily:
这是明确的,在一般情况下它是有道理的......但它是一个有漏洞的抽象,NULL
实际上是0
字面意思,最终可能很容易被误用:
if(some_ptr != NULL){;}
C++0x has nullptr which is now the preferred method as it is explicit and accurate, just be careful about accidental assignment:
C++0x 有 nullptr 现在是首选方法,因为它明确且准确,只是要小心意外分配:
if(some_ptr != nullptr){;}
Until you are able to migrate to C++0x I would argue it's a waste of time worrying about which of these methods you use, they are all insufficient which is why nullptr was invented (along with generic programming issues which came up with perfect forwarding.) The most important thing is to maintain consistency.
在您能够迁移到 C++0x 之前,我认为担心您使用这些方法中的哪一种是浪费时间,它们都不够,这就是发明 nullptr 的原因(以及提出完美转发的通用编程问题) .) 最重要的是保持一致性。
In C
在 C
C is a different beast.
C是一个不同的野兽。
In C NULL can be defined as 0 or as ((void *)0), C99 allows for implementation defined null pointer constants. So it actually comes down to the implementation's definition of NULL and you will have to inspect it in your standard library.
在 C 中 NULL 可以定义为 0 或 ((void *)0),C99 允许实现定义的空指针常量。所以它实际上归结为 NULL 的实现定义,你必须在你的标准库中检查它。
Macros are very common and in general they are used a lot to make up for deficiencies in generic programming support in the language and other things as well. The language is much simpler and reliance on the pre-processor more common.
宏非常常见,一般来说,它们被大量使用以弥补语言和其他方面对通用编程支持的不足。该语言要简单得多,并且对预处理器的依赖更为普遍。
From this perspective I'd probably recommend using the NULL
macro definition in C.
从这个角度来看,我可能会建议使用NULL
C 中的宏定义。
回答by GManNickG
I use if (ptr)
, but this is completely not worth arguing about.
我使用if (ptr)
,但这完全不值得争论。
I like my way because it's concise, though others say == NULL
makes it easier to read and more explicit. I see where they're coming from, I just disagree the extra stuff makes it any easier. (I hate the macro, so I'm biased.) Up to you.
我喜欢我的方式,因为它简洁,尽管其他人说它== NULL
更容易阅读和更明确。我知道他们来自哪里,我只是不同意额外的东西会让它变得更容易。(我讨厌宏,所以我有偏见。)由你决定。
I disagree with your argument. If you're not getting warnings for assignments in a conditional, you need to turn your warning levels up. Simple as that. (And for the love of all that is good, don't switch them around.)
我不同意你的论点。如果您没有在有条件的作业中收到警告,则需要提高警告级别。就那么简单。(为了爱一切美好的事物,不要改变它们。)
Note in C++0x, we can do if (ptr == nullptr)
, which to me doesread nicer. (Again, I hate the macro. But nullptr
is nice.) I still do if (ptr)
, though, just because it's what I'm used to.
请注意,在 C++0x 中,我们可以做if (ptr == nullptr)
,这对我来说确实读起来更好。(同样,我讨厌宏。但nullptr
它很好。)if (ptr)
不过,我仍然这样做,只是因为这是我习惯的。
回答by James McNellis
Frankly, I don't see why it matters. Either one is quite clear and anyone moderately experienced with C or C++ should understand both. One comment, though:
坦率地说,我不明白为什么这很重要。任何一个都非常清楚,任何对 C 或 C++ 有一定经验的人都应该理解两者。不过,有一条评论:
If you plan to recognize the error and not continue executing the function (i.e., you are going to throw an exception or return an error code immediately), you should make it a guard clause:
如果您打算识别错误而不继续执行函数(即,您将立即抛出异常或返回错误代码),则应将其设为保护子句:
int f(void* p)
{
if (!p) { return -1; }
// p is not null
return 0;
}
This way, you avoid "arrow code."
这样,您就可以避免“箭头代码”。
回答by Mark Ransom
Personally I've always used if (ptr == NULL)
because it makes my intent explicit, but at this point it's just a habit.
我个人一直使用if (ptr == NULL)
它,因为它使我的意图明确,但在这一点上它只是一种习惯。
Using =
in place of ==
will be caught by any competent compiler with the correct warning settings.
使用=
in place of==
将被任何具有正确警告设置的合格编译器捕获。
The important point is to pick a consistent style for your group and stick to it. No matter which way you go, you'll eventually get used to it, and the loss of friction when working in other people's code will be welcome.
重要的一点是为您的团队选择一致的风格并坚持下去。不管你走哪条路,你最终都会习惯它,在其他人的代码中工作时减少摩擦将是受欢迎的。
回答by Daniel Hershcovich
Just one more point in favor of the foo == NULL
practice:
If foo
is, say, an int *
or a bool *
, then the if (foo)
check can accidentally be interpreted by a reader as testing the value of the pointee, i.e. as if (*foo)
. The NULL
comparison here is a reminder that we're talking about a pointer.
还有一点支持这种foo == NULL
做法:如果foo
是,比如说, anint *
或 a bool *
,那么if (foo)
检查可能会被读者意外地解释为测试指针对象的值,即作为if (*foo)
。NULL
这里的比较提醒我们正在谈论指针。
But I suppose a good naming convention makes this argument moot.
但我想一个好的命名约定使这个论点没有实际意义。
回答by Derek
The C Programming Language(K&R) would have you check for null == ptr to avoid an accidental assignment.
C 编程语言(K&R) 会让您检查 null == ptr 以避免意外分配。
回答by dwo
Actually, I use both variants.
实际上,我使用这两种变体。
There are situations, where you first check for the validity of a pointer, and if it is NULL, you just return/exit out of a function. (I know this can lead to the discussion "should a function have only one exit point")
在某些情况下,您首先检查指针的有效性,如果它为 NULL,您只需返回/退出函数。(我知道这会导致讨论“函数是否应该只有一个退出点”)
Most of the time, you check the pointer, then do what you want and then resolve the error case. The result can be the ugly x-times indented code with multiple if's.
大多数情况下,您检查指针,然后执行您想要的操作,然后解决错误情况。结果可能是带有多个 if 的丑陋的 x 次缩进代码。
回答by Darryl
If style and format are going to be part of your reviews, there should be an agreed upon style guide to measure against. If there is one, do what the style guide says. If there's not one, details like this should be left as they are written. It's a waste of time and energy, and distracts from what code reviews really ought to be uncovering. Seriously, without a style guide I would push to NOT change code like this as a matter of principle, even when it doesn't use the convention I prefer.
如果风格和格式将成为您评论的一部分,则应该有一个商定的风格指南来衡量。如果有的话,按照风格指南说的去做。如果没有,像这样的细节应该保留原样。这是一种时间和精力的浪费,并且分散了代码真正应该揭示的内容。说真的,如果没有样式指南,我会根据原则推动不要像这样更改代码,即使它不使用我喜欢的约定。
And not that it matters, but my personal preference is if (ptr)
. The meaning is more immediately obvious to me than even if (ptr == NULL)
.
并不重要,但我个人的偏好是if (ptr)
。对我来说,这个意思甚至比 更明显if (ptr == NULL)
。
Maybe he's trying to say that it's better to handle error conditions before the happy path? In that case I still don't agree with the reviewer. I don't know that there's an accepted convention for this, but in my opinion the most "normal" condition ought to come first in any if statement. That way I've got less digging to do to figure out what the function is all about and how it works.
也许他是想说最好在快乐路径之前处理错误条件?在这种情况下,我仍然不同意审稿人的意见。我不知道对此有一个公认的约定,但在我看来,最“正常”的条件应该出现在任何 if 语句中。这样我就可以减少挖掘功能来弄清楚该功能的全部内容以及它是如何工作的。
The exception to this is if the error causes me to bail from the function, or I can recover from it before moving on. In those cases, I do handle the error first:
例外情况是,如果错误导致我退出函数,或者我可以在继续之前从中恢复。在这些情况下,我首先处理错误:
if (error_condition)
bail_or_fix();
return if not fixed;
// If I'm still here, I'm on the happy path
By dealing with the unusual condition up front, I can take care of it and then forget about it. But if I can't get back on the happy path by handling it up front, then it should be handled afterthe main case because it makes the code more understandable. In my opinion.
通过预先处理异常情况,我可以处理它,然后忘记它。但是如果我不能通过预先处理它回到快乐的道路上,那么它应该在主要案例之后处理,因为它使代码更易于理解。在我看来。
But if it's not in a style guide then it's just my opinion, and your opinion is just as valid. Either standardize or don't. Don't let a reviewer pseudo-standardize just because he's got an opinion.
但如果它不在风格指南中,那么这只是我的意见,你的意见同样有效。要么标准化,要么不标准化。不要让审稿人仅仅因为他有意见就伪标准化。