两者都是语法正确的 C,编译器必须处理它。但是编译器可能会根据配置发出警告甚至错误(例如 gcc 中的 -Werror),因为其中一个非常可疑,以至于您永远不会认为它是故意的。当您使用 if (x = 0) { ... } 之类的东西(将零分配给 x 并在零非零时运行该块)时,您几乎总是实际上是指 if (x == 0) { ... }(如果 x 为零则运行该块)。
现在让我们来看看为什么 if ((x = 0)) { ... } 不被认为足够可疑以保证
相同类型的警告(这个特定的代码仍然是可疑的,因为条件总是计算为零并且主体永远不会运行)......
一些 C 开发人员(我就是其中之一)使用的一种习惯用法是将赋值放在括号中,并利用即使赋值本身也有一个值并且它是赋值的特性。
例子:
#include <stdio.h>
int main(int argc, char **argv)
{
int c;
while ((c = getchar()) != '\n')
printf("Character: '%c' (0x%02x)\n", c, c);
return 0;
}
测试示例:
$ ./test
Hello!
Character: 'H' (0x48)
Character: 'e' (0x65)
Character: 'l' (0x6c)
Character: 'l' (0x6c)
Character: 'o' (0x6f)
Character: '!' (0x21)
重要的部分是条件(c = getchar()) != '\n',您首先将getchar() 的结果分配给c,然后检查它的特定值。在这种情况下,我们从标准输入一个接一个地读取字符,直到一行的 and (技术上,直到我们读取一个 \n 字符)。这样做的主要优点是它允许您将getchar() 填充到测试中。否则,您将不得不使用逗号符号、带中断的无限循环,或者将其放在循环之前和循环末尾。
有时您会与非零值进行比较,例如\n、-1 等,但有时您会与零进行比较,或者在使用指针时与NULL 进行比较。让我们为NULL 找一个例子,这在内存分配中很常见。
char *p;
if ((p = malloc(50)) == NULL) {
...handle error...
}
当然可以这样写:
char *p;
p = malloc(50);
if (p == NULL) {
...handle error...
}
但根据您的口味,您也可以使用:
char *p;
if (!(p = malloc(50))) {
...handle error...
}
或者甚至反过来(顺便说一句,这违背了 my 总是首先处理错误情况的偏好):
char *p;
if ((p = malloc(50))) {
...do stuff...
} else {
...handle error...
}
在最后一种情况下,条件是(p = malloc(50)),它完全等同于p = malloc(50),但后者非常可疑,因为已经提到的常见错误是在C中执行赋值而不是比较和派生语言。请注意,这不仅与可疑编译器有关,还与人类阅读代码和查看潜在错误有关。
多余的括号只是告诉读者和编译器这个赋值绝对是故意的,而不是那个常见错误的发生。