NULL 总是假的吗?

假设 NULL在 C 语言中总是翻译成 false 是否安全?

void *somePtr = NULL;


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

还是应该对 NULL的值进行显式检查?

55492 次浏览

假设任何事都不安全。

一个明确的检查也更加清楚你在测试什么。

NULL被定义为一个常量指针,它保证指向内存中无用/不存在的位置。NULL的大多数实现都是 ((void *)0),但是这并不是强制性的。

* NULL 的目标总是0x00L。您可以认为这是假的,但要确保始终进行显式检查。

是的。NULL 的计算结果为 false,因为 C 认为任何非零值为 true,任何零值为 false。NULL 本质上是 zero地址,在比较中也是这样处理的,我相信在布尔检查中会被提升为 int。我希望您的代码对于任何熟悉 C 的人来说都是可读的,尽管我可能会将检查显式化。

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

档号: http://en.wikipedia.org/wiki/Null_pointer#Null_pointer

‘ C’语言可以追溯到(void *)0实际上可以作为有效指针的时代。就在不久前,8080和 Z80微处理器的中断向量地址还是0。面对这样的架构选择,它只能让头文件声明 NULL 的值。有一些编译器,现在早已被遗忘,其中 nULL 不等于(void *)0(0xffff 是下一个替代方案) ,因此给了 if ()语句未定义行为。

C + + 仁慈地结束了这一切,一个空指针是可赋值的,并且可以针对0进行测试。

是的,差不多。

首先,NULL 是一个 typedef。我可以通过在之前包含的标题中说这句话来完全搞垮你

#define NULL 1

This might not make a lot of sense, but since when has other people's code ever made sense? :)

Also, while it's probably syntactically safe, it's not semantically correct. NULL means "nothing", neither true or false or a boolean value or int or string. It means "a symbol for nothing". So testing for NULL is more like a philisophical issue: If a tree falls in the forest, and if(listener), does it make a sound?

Do everyone a favor and be clear about testing against NULL.

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

来自 常见问题解答:

问: 测试非空指针的缩写指针比较“ if (p)”是否有效?如果空指针的内部表示是非零的呢?

答: 它总是有效的。

NULL 只是一个预处理器定义。在工作室。一般来说,只有疯子才会重新定义它,但这是有可能的。举个例子:

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


void main()
{


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

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

是的,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将计算为真,因为 0将被提升到 (void*)0,这是一个空指针。这也意味着非空指针不能等于空指针。

让我们看看负运算符。

这就是逻辑非的结果!如果其操作数的值比较不等于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只能在 p为空指针时求值为 true,在 p不为空指针时求值为 false。

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

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

6.3转换

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

6.3.2.3指标

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

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

6.5.9相等运算符

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

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

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

6.5.3.3一元算术运算符

这就是逻辑非的结果!如果其操作数的值比较不等于0,则为0; 如果其操作数的值比较等于0,则为1。结果的类型为 int。就是这个表情!E 等于(0 = = E)。

!ptr也是如此。

6.8.4.1 if 语句

If 语句的控制表达式应该是标量类型。

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

注意,标量类型算术类型指针类型(见“6.2.5种类型”,第21条):

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


什么是 NULL?

宏 NULL 在 < stddef.h > (和其他头)中定义为 空指针常数;


空指针常量的值是多少?

值为 0的整数常量表达式,或者将此类表达式强制转换为 Void * ,称为空指针常量。

例子定义:

#define NULL ((void*)0)


评估 if (NULL)

If (表达式)语句

If (expression)语句 else 语句

在这两种形式中,如果表达式比较不等于0,则执行第一个子语句。 在 else 形式中,如果表达式比较相等,则执行第二个子语句 6.8.4.1语文133 ISO/IEC 9899: TC3委员会草案ーー2007年9月7日 如果第一个子语句是通过标签达到的,则第二个子语句不是 处决。


因此,如果编译器符合 ISOC99,那么您可以假设下面的语句将始终执行。

if (!NULL) { statement; }


以上报价来自 ISO/IEC9899:1999(C99)。您可以阅读它 给你

是的:

C 标准6.3.2.3

值为0的整数常量表达式,或类似的 表达式转换为 void * 类型,称为空指针 如果空指针常量被转换为指针类型, 结果指针,称为空指针,保证比较 不等于指向任何对象或函数的指针。

6.3.2.6

任何指针类型都可以转换为整数类型 前面指定的,结果是实现定义的 结果不能用整数类型表示,则行为 是不确定的。结果不必在值的范围内 任何整数类型。

-

当任何标量值转换为 _ Bool 时,如果 值比较为0; 否则,结果为1

据我所知,这种假设并不总是安全的。因为,根据程序中包含的标题,可以重新定义它。但是根据标准,空指针常量保证不指向任何实际对象,并且具有 void *类型。

在我们的示例中,声明 void *somePtr = NULL也可以是 void *somePtr = 00作为空指针。

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

这就意味着,在这个特定点上计算 *somePtr可能会导致 false。

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