NULL总是假吗?

Syd*_*ius 62 c null pointers

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

void *somePtr = NULL;

if (!somePtr) {
  /* This will always be executed? */
}
Run Code Online (Sandbox Code Playgroud)

或者应该明确检查价值NULL

tva*_*son 63

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

在C和C++编程中,两个空指针保证比较相等; ANSI C保证在与整数类型进行比较时,任何空指针都将等于0; 此外,宏NULL被定义为空指针常量,即值0(作为整数类型或转换为指向void的指针),因此空指针将比较等于NULL.

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

  • 在某些情况下,显式检查可能更清楚,但这是C语言,该语言保证有效.:) (4认同)
  • 你不要转换为int.你将0与指针进行比较.0是空指针常量.如果将空指针常量与指针进行比较,则空指针常量将成为正确类型的空指针.并且空指针比较不等于每个有效指针.这就是他想要的 (3认同)
  • 如果所有我的c代码使用那些如果东西现在无效,我会哭 (2认同)

aka*_*tos 18

假设什么都不安全.

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

  • +1显式总是优于隐式. (11认同)
  • @Peter Rowell:很长一段时间,我使用 #define NIL(x) ((x)0) 来大致实现这种效果:NIL(foo)、NIL(char *)、NIL(bar) 等。 (2认同)

Han*_*ant 18

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

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

  • 关于你的C++句子:这是错误的。0 不是空指针。0 是空指针常量。无效 *p = 0; 现在,p 是一个空指针。这是有区别的,因为空指针具有指针类型,其中空指针常量具有整数类型并且是常量表达式 (2认同)
  • C99保证将0强制转换为指针类型也将是空指针-我从不费心阅读以前的标准,所以不知道何时发生这种情况... (2认同)
  • 在我为其编写 mmu 代码的每个架构上,0 仍然是一个完全有效的地址。这只是许多 C 运行时的约定,导致其使用无效。在现代 Linux 中,作为 root,您可以使用 MAP_FIXED 将对象映射到 0。在不久前的 UNIX 中,通常将只读零页映射到零,这样 strcmp(NULL, ...) 就不会导致错误,而只会匹配空字符串。 (2认同)

Cap*_*ult 14

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

comp.lang.c FAQ:

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

答:它总是有效的.


klu*_*utt 7

是的,if(!p)有效并保证有效。

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

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

这意味着这(void*)0是一个空指针。这也意味着 ifp是指针,则p==0相当于p==(void*)0

这也意味着 ifp不是空指针,那么p==(void*)0将计算为0

到目前为止,一切都很好。

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

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

请注意,“任何两个空指针比较都应该相等”。这意味着 ifp是空指针,则将p==0评估为 true,因为0将提升为(void*)0which is 空指针。这也意味着非空指针不能等于空指针。

让我们看一下否定运算符。

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

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

这告诉我们,与定义!p相同,与上面提到的p==0相同。p==(void*)0

考虑到所有空指针都是相等的事实,这意味着p==(void*)0仅当 是空指针时才能计算为 true p,并且如果p不是空指针则只能计算为 false。

所以是的,if(!p)这是检查是否p为空指针的完全安全的方法。


Ral*_*lph 5

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

6.3转换

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

6.3.2.3指针

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

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

6.5.9平等经营者

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

6当且仅当两个都是空指针,并且两个都是[...]时,两个指针比较相等

因此,当且仅当为空指针时,它ptr==0是1(并且ptr!=0是0)ptr

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是一个空指针。

  • 引用的文件可在 http://www.open-std.org/jtc1/sc22/wg14/www/standards 上找到 (2认同)