while(foo)
和while(foo != NULL)
的等价性吗?另外:while(!foo)
和 while(foo == NULL)
呢?我知道!代表"不",但这就是我所知道的全部了。
while(foo)
和while(foo != NULL)
的等价性吗?另外:while(!foo)
和 while(foo == NULL)
呢?foo
是指针类型,while (foo)
和while (foo != NULL)
完全等价。两者也等价于while (foo != 0)
。(在我看来,while (foo != NULL)
更清晰地表达了意图。)if()
,while()
和其他一些情况),如果条件与零不相等,则将表达式视为true,如果条件与零相等,则将其视为false。
NULL
是一个宏,它扩展为实现定义的空指针常量。将指针值与NULL
进行比较,对于空指针产生真值,对于任何非空指针产生假值。0
是一个空指针常量[*]。(这并不意味着空指针具有0x00000000
或类似内容的相同位表示,尽管它经常具有;它意味着源代码中的常量0
可以表示一个空指针。)正如您所期望的那样,将指针值与空指针常量进行比较可以告诉您该指针是否为空指针。在while (foo)
中,与零的比较是隐含的——但它仍然测试foo
是否为空指针。while (foo)
将foo
与0
进行比较,这等价于将其与适当类型的“零”进行比较。 while (foo)
始终等价于while (foo != 0)
。对于浮点值,它也等价于while (foo != 0.0)
。对于字符值,它等价于while (foo != '\0')
。并且,正如我们所看到的,对于指针值,它等价于while (foo != NULL)
。0
的值,如果条件为真,则产生一个值为1
的值——但任何非零值都会通过与零的隐式不等式比较而被视为真。)0
的整数常量表达式,或将这样的表达式强制转换为void*
。空指针常量不一定是指针类型,但是将其转换为指针类型会产生空指针值。将指针值与0
进行比较会导致0
被隐式转换为指针类型,以便可以进行比较。0
既可以是 int
类型的表达式,也可以是空指针常量;我可以理解这可能会引起混淆。) - Keith Thompson#define NULL 0
是有效的,#define NULL ((void*)0)
也是如此。后者有优势,但两者都是符合规范的。 - chux - Reinstate Monica#define NULL ((void*)0)
是无效的。(N1570 6.5.1p5没有说括号中的空指针常量是空指针常量。)但在实际使用中,它肯定是有效的。 - Keith Thompsonwhile(foo);
并且
while(foo != NULL)
这两个表达式等效,因为NULL是一个宏,可以扩展为0
、(void*)0
或0L
。在C语言中,0被认为是假(任何非零数字都是真),因此它们等同。
while(foo); //while foo isn't 0
while(foo != NULL) //expands to while(foo != 0) < while foo isn't 0
foo
的类型而定。考虑使用double foo
。while(foo);
是可以的,但是while(foo != NULL)
无法编译通过:“二元运算符!=
的操作数无效”,这取决于NULL
的定义方式,它应该是一个空指针常量,而不是像这里建议的0
。 - chux - Reinstate Monica#define NULL ((void *)0)
。MS Visual 2010在编译为C时使用#define NULL ((void *)0)
。也许你想到的是另一种语言如C++中如何定义NULL
。 - chux - Reinstate MonicaNULL
可以是(void*)0
,但不是0
,也不是0L
。你的答案表示它可以是0
,或(void*)0
或0L
。你的评论“大多数实现确实使用0作为NULL
”,并没有得到任何例证,而对比起来有两个反例。 - chux - Reinstate MonicaNULL
可以是 0
或 (void *)0
,我认错了。 - chux - Reinstate Monicawhile
(expression
) 循环语句会在expression
的值为非零时重复执行包含的代码块。当expression
的值为0时,while
循环结束。
如果expression
是指针类型,则只要指针值不是std::nullptr
或NULL
,就被认为是非0。
!
运算符是布尔型的非运算符。
因此
while (foo)
和
while (foo != NULL)
std::nullptr
是 C++ 中的一个概念。我们现在正在进行一道 C++ 相关的问题。 - Bill LynchNULL
是一个符号常量,你可以把它看作一种替换文本。编译器会将NULL
替换成零,因此写while (foo != NULL)
与写while (foo != 0)
是相同的。请记住,==
表示左侧的内容等于右侧的内容,而!=
表示左侧的内容不等于右侧的内容。
在C语言中,数字0始终表示false,而其他数字表示true。因此,while (foo != 0)
等同于说“只要foo为true,就运行此循环中的代码”。例如,while (1)
等同于说“永远运行此循环中的代码”,因为1始终不等于零,因此始终为true。
foo
,那么它等同于foo != 0
,这就像是一种快捷方式,相当于在问“foo是否为真?”。!
表示“非”,因此询问!foo
等同于询问“foo不为真吗?”,换句话说,“foo是否为假?”。这意味着while (!foo)
与“当foo为假时运行此循环中的代码”相同,这与while (foo == 0)
相同,因为零表示假,这也与while (foo == NULL)
相同,因为NULL
表示零。while (foo)
中,计算机将询问“foo是否非零?”,如果是,则继续循环。现在,如果你有while (!foo)
,计算机将询问“foo是否非非零?”,如果是,则继续循环。只有当括号中的表达式结果为假时,循环才会停止。
NULL
在多个标准头文件中定义,它不像 if
和 while
那样是一个关键字,你需要包含定义它的头文件才能使用它。其原理是当指针指向地址零时,它被称为“空指针”,这就是为什么它被称为NULL
,它用于表达“零地址”而不是仅表示“零值”。
编辑:
正如 Matt McNabb 所指出的那样,NULL
可以被定义为 0
或者 (void *)0
。为了消除任何疑虑,我引用了 C11 标准:
值为 0 的整数常量表达式,或者被转换为类型void *的这样一个表达式,称为空指针常量。
稍后在文中提到:
宏 NULL 在 <stddef.h>(和其他头文件)中被定义为一个空指针常量;参见 7.19 节。
然后,在第 7.19 节中:
3 这些宏是
NULL
它扩展为一个实现定义的空指针常量;以及
offsetof(type, member-designator)
它扩展为...
文本继续。因此,(void *)0
和 0
都是有效的实现定义的空指针常量。
NULL
可以是 0
或 (void *)0
。 - M.MNULL
可以是 0
或 (void *)0
。 - chux - Reinstate Monicawhile循环可以这样运行:
while(1) //This will run forever.
while(true) //This will run forever.
NULL
就像0一样,所以如果你有while(foo != NULL)
,这意味着当foo不等于0时(也就是等于1或其他值),就运行它。
foo
是一个指针,那么while(foo)
的定义是while(foo != NULL)
。因此它们是等价的。 - M.M