if((x = 0))在C中的含义是什么?

时间:2014-09-21 15:06:23

标签: c gcc gcc-warning

显然,在gcc / C中,编译器在

时编译
if ((x=0)){ some code }

时使用

if (x=0){ some code }
使用

,然后编译器拒绝编译。

两者之间有什么区别?

作为备注,我知道x==0x=0之间的区别。我正在探索C遇到一些奇怪的代码时的行为。

3 个答案:

答案 0 :(得分:48)

代码方面没有区别。

所有发生的事情都是说x=0而不是x==0是一个常见的错误,大多数编译器会在看到它时发出警告(或错误,在你的情况下)。额外的一组括号是关闭编译器的常用技巧 - 相当于说'是的,我真的打算这样做'。

答案 1 :(得分:36)

两者在语法上都是正确的C,编译器必须处理它。但是,编译器可能会根据配置发出警告甚至错误(例如gcc中的-Werror),因为其中一个是如此可疑,以至于你永远不会想到它是故意的。当您使用if (x = 0) { ... }之类的内容时(将{0}赋值为0并运行该块,如果零为非零),您几乎总是实际意味着x(如果if (x == 0) { ... }则运行该块}是零)。

现在让我们了解为什么x不被认为可疑 相同类型的警告(这个特殊的代码仍然是可疑的,因为条件总是评估为零而且正文永远不会运行)...

有些C开发人员使用了一个习惯用法(我就是其中之一),你将一个赋值括在括号中并利用这个特征,即使赋值本身也有一个值,它就是赋值。

示例:

if ((x = 0)) { ... }

测试示例:

#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字符)。这样做的主要优点是它允许您将\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...
}

在最后一种情况下,条件是char *p; if ((p = malloc(50))) { ...do stuff... } else { ...handle error... } ,它与(p = malloc(50))完全相同,但后者非常可疑,因为已经提到的常见错误执行了赋值C语言和派生语言的比较请注意,这不仅涉及可疑编译器,还涉及人们阅读代码并查看潜在错误。

冗余括号只是一种告诉读者和编译器的方法,这种分配绝对是有意的,而且不是常见错误的发生。

答案 2 :(得分:19)

除非你有-Werror,否则代码不应该“拒绝”编译。如果您启用了警告,它可能会告诉您:

  

警告:建议用作真值的赋值括号[-Whatarentheses]            while (*dest++ = *src++)

具体来说,GCC docs对警告的目的说了这个:

  

如果在某些上下文中省略括号,请发出警告,例如何时   在预期真值的上下文中有一个赋值,   或者当运算符嵌套时,人们经常会得到优先级   困惑。