我们如何检查指针是否为NULL指针?

cpu*_*uer 42 c null-pointer

我一直认为只会if(p != NULL){..}做这项工作.但在阅读Stack Overflow问题后,似乎没有.

那么在吸收了那个说明NULL指针可能具有非零值的问题的所有讨论之后检查NULL指针的规范方法是什么?

cni*_*tar 52

我总是认为,如果(p!= NULL){..}将完成这项工作.

它会.

  • @Lundin:if语句中的条件只需要可以转换为布尔值; 在那种情况下,`p`相当于`p!= NULL`,它纯粹是你所选择的美学问题.既不比另一个更安全或"更好的练习". (4认同)
  • 这种样式被认为比if(p)更好,因为if语句中的表达式应该是布尔值,而在这种情况下"p"是指针,而不是bool.使用==或!=显式检查零被认为是更安全和更好的做法(MISRA-C:2004 13.2). (3认同)
  • @Mike Seymour 我比较反对`if (p)`,因为我仍然需要停下来考虑一下。正如你所说,这可能是经验问题;我只使用 C 和 C++ 30 年,所以毫无疑问它会及时出现在我身上。(说真的,这可能是另一种体验的问题;在开始使用 C 之前,我广泛使用了 Pascal 和 Modula-2,并且已经习惯了严格的类型。我从来没有对 C 在这里的松散感到满意,隐式转换无处不在那个地方。) (3认同)
  • @James:好的,我说错误的说有经验的程序员不会发现任何一种形式都不清楚.这让我感到惊讶,但我无法与证据争论. (2认同)
  • @Lundin:在C中,是的.在C++中,`(void*)0`不是`NULL`的有效定义; 它必须可以转换为任何指针类型,并且C++不允许从`void*`到其他指针类型的隐式转换.因此`NULL`必须定义为整数类型的零值文字,并将其与另一个数字类型进行比较不会发出警告.(C++ 0x将通过引入`nullptr`来解决这个问题,`nullptr`是一种可转换为指针类型但不能转换为数字类型的类型,但在此之前我们必须尽可能地混淆.) (2认同)

Jam*_*nze 29

首先,要100%清楚,这里C和C++之间没有区别.第二,你引用的Stack Overflow问题并没有讨论空指针; 它引入了无效指针; 指针,至少就标准而言,仅通过尝试比较它们就会导致未定义的行为.通常无法测试指针是否有效.

最后,有三种检查空指针的方法:

if ( p != NULL ) ...

if ( p != 0 ) ...

if ( p ) ...
Run Code Online (Sandbox Code Playgroud)

所有工作,无论机器上的空指针表示如何.所有这些都以某种方式产生误导; 你选择哪一个是选择最不好的问题.形式上,前两个是编译器的缩写; 常量NULL0转换为类型的空指针p,并将转换结果进行比较p.无论空指针的表示如何.

第三个略有不同:p隐式转换为bool.但是隐式转换被定义为结果p != 0,所以你最终会得到同样的结果.(这意味着使用第三种样式确实没有有效的参数 - 它与隐式转换混淆,没有任何抵消利益.)

你喜欢的前两个中哪一个主要是风格问题,也许部分取决于你在其他地方的编程风格:根据所涉及的习语,其中一个谎言将比另一个更麻烦.如果它只是一个比较的问题,我认为大多数人会喜欢NULL,但在类似的情况下f( NULL ),将选择f( int )的重载,而不是指针的重载.同样,如果f是函数模板,f( NULL )则将实例化模板int.(当然,一些编译器,比如g ++,如果NULL在非指针上下文中使用,会产生警告;如果你使用g ++,你真的应该使用NULL.)

当然,在C++ 11中,首选的习惯是:

if ( p != nullptr ) ...
Run Code Online (Sandbox Code Playgroud)

,这避免了其他解决方案的大多数问题.(但它不兼容C :-).)

  • @ vompile-fan这不是合法的C,也不是合法的C ++。在C中,您可以使用`main`的地址,前提是可见`main`的声明。在C ++中,我不确定。但是,在这两种语言中,都没有将函数的指针隐式转换为“ void *”,并且在这两种语言中,都不能将指针与整数(空指针常量除外)进行比较。出于历史原因,通常会接受第一个(有警告或无警告);但是,接受第二个的编译器严重损坏。 (2认同)

Sim*_*ter 10

编译器必须提供一致的类型系统,并提供一组标准转换.整数值0和NULL指针都不需要用全零位表示,但编译器必须注意将输入文件中的"0"标记转换为整数零的正确表示,并转换为指针类型必须从整数转换为指针表示.

这意味着

void *p;
memset(&p, 0, sizeof p);
if(p) { ... }
Run Code Online (Sandbox Code Playgroud)

并不保证在所有目标系统上的行为相同,因为您在此处对位模式进行了假设.

作为一个例子,我有一个没有内存保护的嵌入式平台,并将中断向量保持在地址0,所以按照惯例,整数和指针在转换时与0x2000000进行异或,这使得(void*)0指向一个地址在解除引用时生成总线错误,但是使用if语句测试指针将首先将其返回到整数表示,然后全部为零.


Mik*_*our 7

空指针的实际表示在这里是无关紧要的.值为零的整数文字(包括0和任何有效的定义NULL)可以转换为任何指针类型,给出空指针,无论实际表示如何.所以p != NULL,p != 0并且p都是非空指针的有效测试.

如果你写了类似扭曲的东西p != reinterpret_cast<void*>(0),你可能会遇到空指针的非零表示问题,所以不要这样做.

虽然我刚刚注意到你的问题被标记为C以及C++.我的答案是指C++,其他语言可能不同.你使用哪种语言?


pmg*_*pmg 6

显然,您引用的线程是关于C++.

C您的代码段中将始终有效。我喜欢简单的if (p) { /* ... */ }