NULL总是假吗?

时间:2009-01-20 00:31:47

标签: c null pointers

是否可以安全地假设NULL在C中始终转换为false?

void *somePtr = NULL;

if (!somePtr) {
  /* This will always be executed? */
}

或者是否应该对NULL的值进行明确检查?

14 个答案:

答案 0 :(得分:49)

是。 NULL的计算结果为false,因为C认为任何非零值为true,任何零值为false。 NULL本质上是zero地址,并且在比较中被视为这样,并且我相信将被提升为布尔检查的int。我希望你的代码对任何熟悉C的人都是可读的,尽管我可能会明确地进行检查。

  

在C和C ++编程中,两个为null   指针保证比较   等于; ANSI C保证任何null   指针在a中等于0   与整数类型比较;   此外,定义了宏NULL   作为空指针常量,即   值0(作为整数类型或   转换为指向void的指针,所以a   空指针将比较等于   NULL。

参考:http://en.wikipedia.org/wiki/Null_pointer#Null_pointer

答案 1 :(得分:16)

假设任何事都是不安全的。

对您正在测试的内容进行明确检查也很清楚。

答案 2 :(得分:15)

'C'语言可以追溯到一个时代,其中(void *)0实际上可以是一个有效的指针。不久之前,8080和Z80微处理器在地址0处有一个中断向量。面对这样的架构选择,除了让头文件声明NULL值之外,它什么也做不了。那里有一些编译器,现在很久都被遗忘了,其中NULL不等于(void *)0(0xffff是下一个选择),因此给你的if()语句定义了未定义的行为。

C ++仁慈地结束了这一点,一个空指针可以从0分配和测试。

答案 3 :(得分:11)

是(至少对于任何符合标准的C编译器!)

来自comp.lang.c FAQ

  

问:用于测试非空指针的缩写指针比较``if(p)''是否有效?如果空指针的内部表示非零,该怎么办?

     

答:它总是有效的。

答案 4 :(得分:7)

我的ISO / IEC 9899:TC3(委员会草案,2007年9月7日)副本:

  

6.3转换

     

1多个运算符会自动将操作数值从一种类型转换为另一种类型。

     

6.3.2.3指针

     

3值为0 [...]的整数常量表达式称为空指针常量。如果将空指针常量转换为指针类型,则可以保证生成的指针(称为空指针)与指向任何对象或函数的指针不相等。

到目前为止,ptr!=0对每个非null ptr都是true(1),但是它仍然是开放的,如何比较两个null指针。

  

6.5.9相等运算符

     

5 [...]如果一个操作数是一个指针,另一个是空指针常量,则该空指针常量将转换为指针的类型。

     

6当且仅当两个都是空指针,两个都是[...]

时,两个指针比较相等

因此,当且仅当ptr==0为空指针时,ptr!=0为1(而ptr为0)。

  

6.5.3.3一元算术运算符

     

5逻辑求反运算符的结果!如果其操作数的值比较不等于0,则为0;如果其操作数的值比较等于0,则为1。结果的类型为int。表达式!E等效于(0 == E)。

!ptr也是如此。

  

6.8.4.1 if语句

     

1 if语句的控制表达式应为标量类型。

     

2在两种形式中,如果表达式比较不等于0,则执行第一个子语句。

请注意,标量类型算术类型指针类型(请参见“ 6.2.5类型”,第21条) 。放在一起,我们有:

  • if (ptr)成功⇔ptr!=0为1⇔ptr不是空指针。
  • if (!ptr)成功⇔ptr==0为1⇔ptr为空指针。

答案 5 :(得分:5)

NULL只是一个预处理器定义。它在stdio.h中。通常,只有疯狂的人会重新定义它,但这是可能的。一个例子:

#include <stdio.h>
#ifdef NULL
#undef NULL
#define NULL 1
#endif

void main()
{

        if (NULL)
                printf("NULL is true\n");
        else
                printf("NULL is false\n");
}

此代码将打印“NULL为true”。如果你不相信我,试试吧。您的编译器甚至可能不会警告您,您正在做一些奇怪的事情。

答案 6 :(得分:4)

是的,if(!p)有效并且可以正常工作。

  

一个值为0的整数常量表达式,或强制转换为void *的表达式,称为空指针常量。如果将空指针常量转换为指针类型,则保证生成的指针(称为空指针)将不相等的值与指向任何对象或函数的指针进行比较。

https://port70.net/~nsz/c/c11/n1570.html#6.3.2.3p3

这意味着(void*)0是空指针。这也意味着,如果p是指针,则p==0等效于p==(void*)0

这还意味着,如果p不是非空指针,那么p==(void*)0的值将为0

到目前为止,太好了。

  

将空指针转换为另一种指针类型会产生该类型的空指针。任何两个空指针应比较相等。

http://port70.net/~nsz/c/c11/n1570.html#6.3.2.3p4

请注意“任何两个空指针都应相等。” 这意味着,如果p是空指针,则p==0的值将为true,因为{{ 1}}将提升为空指针0。这也意味着非空指针不能等于空指针。

让我们看一下求反运算符。

  

逻辑否定运算符的结果!如果其操作数的值比较不等于0,则为0;如果其操作数的值比较等于0,则为1。结果的类型为int。表达式!E等效于(0 == E)。

http://port70.net/~nsz/c/c11/n1570.html#6.5.3.3p5

这告诉我们(void*)0在定义上与!p相同,与上述p==0相同。

考虑到所有空指针都相等的事实,这意味着p==(void*)0仅在p==(void*)0为空指针时才为true,而在p为空指针时只能为false。不是空指针。

是的,p是检查if(!p)是否为空指针的一种绝对安全的方法。

答案 7 :(得分:2)

NULL被定义为一个常量指针,可以保证指向内存中无用/不存在的位置。 NULL的大多数实现都是((void *)0),但并非必须如此。

答案 8 :(得分:2)

我只是简单地向您推荐C-FAQ的Question 5.3。它回答了这个问题。

答案 9 :(得分:2)


什么是NULL?

  

宏NULL在(和其他标头)中定义为空指针常量


空指针常量的值是什么?

  

值为 0 的整数常量表达式,或将其转换为类型的表达式   void *,称为空指针常量。


评估if(NULL)

  

if(expression)语句

     

if(expression)语句else语句

     

在两种形式中,如果表达式比较不等于0,则执行第一个子语句。   在else形式中,如果表达式比较等于,则执行第二个子语句   §6.8.4.1语言133   ISO / IEC 9899:TC3委员会草案-2007年9月7日WG14 / N1256   到0。如果通过标签到达第一个子陈述,则第二个子陈述不   被执行。


因此,是的,如果编译器符合ISO C99,则可以假定以下语句将始终执行。

if (!NULL) { statement; } 


以上引文来自ISO / IEC 9899:1999(C99)。您可以阅读here

答案 10 :(得分:2)

是的

C标准6.3.2.3

  

整数常量表达式,其值为0,或者这样的整数   转换为void *类型的表达式称为空指针   如果将空指针常量转换为指针类型,   结果指针(称为空指针)可以保证进行比较   不等于指向任何对象或函数的指针。

和6.3.2.6

  

任何指针类型都可以转换为整数类型。除了作为   先前指定的结果是实现定义的。如果   结果不能以整数类型表示,行为   未定义。结果不必在值的范围内   任何整数类型。

-

  

将任何标量值转换为_Bool时,如果将   值比较等于0;否则,结果为1

答案 11 :(得分:0)

是的,主要是。

首先,NULL是一个typedef。我可以通过在先前包含的标题中说出来,让你彻底搞砸了

#define NULL 1

这可能没有多大意义,但是从什么时候开始其他人的代码才有意义? :)

此外,虽然它可能在语法上是安全的,但它在语义上并不正确。 NULL表示“无”,既不是true或false,也不是布尔值或int或字符串。它意味着“无所作为的象征”。因此,测试NULL更像是一个哲学问题:如果树落在森林中,if(listener),它是否发出声音?

帮助每个人,并明确对NULL进行测试。

答案 12 :(得分:0)

根据我的说法,假设并非总是安全的。由于可以根据程序中包含的标题来重新定义它。但是根据标准,可以保证空指针常量不指向任何实际对象,并且类型为void *

在我们的例子中,声明void *somePtr = NULL也可以是void *somePtr = 0,其中0为空指针。

  

“一个值为0的整数常量表达式,或者将其转换为类型void *的表达式称为空指针常量。如果将空指针常量转换为指针类型,则保证生成的指针(称为空指针)将不等于指向任何对象或函数的指针。” https://www.geeksforgeeks.org/few-bytes-on-null-pointer-in-c/

这仅表示在该特定点评估*somePtr可能会导致错误。

关于NULL指针常量的另一参考可以是第944 A.3页的https://www.gnu.org/software/libc/manual/pdf/libc.pdf

答案 13 :(得分:-3)

* NULL始终以0x00L为目标。你可以认为这是假的,但一定要经常做一个明确的检查。