简体   繁体   English

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

[英]What does if((x=0)) mean in C?

So apparently, in gcc/C, a compiler compiles when 显然,在gcc / C中,编译器编译时

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

is used, while when 当使用时

if (x=0){ some code }

is used, then compiler refuses to compile. 使用,然后编译器拒绝编译。

What are the differences between two? 两者有什么不同?

As a note, I know what is the difference between x==0 and x=0 . 作为一个注释,我知道x==0x=0之间有什么区别。 I am just exploring how C behaves when met with some weird codes. 我正在探索C遇到一些奇怪的代码时的行为方式。

There is no difference, code-wise. 代码方面没有区别。

All that's happening is that saying x=0 instead of x==0 is such a common mistake that most compilers will emit a warning (or error, in your case) when they see it. 所有发生的事情都是说x=0而不是x==0是一个常见的错误,大多数编译器在看到它时会发出警告(或错误,在你的情况下)。 The extra set of parentheses is a common trick to shut the compiler up --- the equivalent of saying 'yes, I really meant to do this'. 额外的一组括号是关闭编译器的常用技巧 - 相当于说“是的,我真的打算这样做”。

Both are syntactically correct C and the compiler has to cope with it. 两者在语法上都是正确的C,编译器必须处理它。 But the compiler may, depending on the configuration, issue a warning or even error (eg -Werror in gcc) because one of them is so suspicious that you would never expect it to be intentional. 但是,编译器可能会根据配置发出警告甚至错误(例如gcc中的-Werror),因为其中一个是如此可疑,以至于您永远不会想到它是故意的。 When you use something like if (x = 0) { ... } (assign zero to x and run the block if zero is non-zero), you almost always actually mean if (x == 0) { ... } (run the block if x is zero). 当你使用类似if (x = 0) { ... }赋值零x和运行块,如果零不为零),你几乎总是实际上意味着if (x == 0) { ... } (如果x为零,则运行块)。

Now let's get to why if ((x = 0)) { ... } is not considered suspicious enough to warrant the same type of warning (this particular code is still suspicious because the condition always evaluates to zero and the body is never run)... 现在让我们看看为什么if ((x = 0)) { ... }被认为不足以保证相同类型的警告(这个特定的代码仍然可疑,因为条件总是评估为零并且正文永远不会运行)...

There's an idiom used by some C developers (I'm one of them) where you put an assignment into parentheses and make use of the feature that even the assignment has a value itself and it's the assigned value. 某些C开发人员使用了一个习惯用法(我就是其中之一),你将一个赋值括在括号中并利用这个特性,即使赋值本身也有一个值,它就是赋值。

Example: 例:

#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 the example: 测试示例:

$ ./test
Hello!
Character: 'H' (0x48)
Character: 'e' (0x65)
Character: 'l' (0x6c)
Character: 'l' (0x6c)
Character: 'o' (0x6f)
Character: '!' (0x21)

The important part was the condition (c = getchar()) != '\\n' where you first assign the result of getchar() to c and then check it for a specific value. 重要的部分是条件(c = getchar()) != '\\n' ,其中首先将getchar()的结果赋给c ,然后检查它是否为特定值。 In this very case we are reading characters one by one from the standard input until the and of a line (technically until we read a \\n character). 在这种情况下,我们从标准输入中逐个读取字符,直到行和(在技术上直到我们读取\\n字符)。 The main advantage of doing it this way is that it allows you to stuff the getchar() into the test. 这样做的主要优点是它允许你将getchar()填充到测试中。 You would otherwise have to use the comma notation, an infinite loop with a break, or put it both before the loop and at the end of the loop. 否则你将不得不使用逗号表示法,带有中断的无限循环,或者在循环之前和循环结束时将它放在一起。

Sometimes you compare to non-zero values, like \\n , -1 and similar, but sometimes you compare to zero or, when working with pointers, to NULL . 有时你会比较非零值,比如\\n-1和类似,但有时你会比较为零,或者在使用指针时,比较为NULL Let's find an example for NULL , which is pretty common with memory allocation. 让我们找一个NULL的例子,这在内存分配中很常见。

char *p;

if ((p = malloc(50)) == NULL) {
    ...handle error...
}

Of course you could write it as: 当然你可以把它写成:

char *p;

p = malloc(50);
if (p == NULL) {
    ...handle error...
}

But depending on your taste you could also use: 但根据您的口味,您还可以使用:

char *p;

if (!(p = malloc(50))) {
    ...handle error...
}

Or even turn it the other way round (which btw goes against my preference of always handling the error case first): 或者甚至将它转向另一个方向(顺便说一下,我总是首先处理错误情况):

char *p;

if ((p = malloc(50))) {
    ...do stuff...
} else {
    ...handle error...
}

In the last case, the condition is (p = malloc(50)) which is exactly equivalent to p = malloc(50) but the latter is highly suspicious because of the already mentioned common mistake of performing assignment instead of comparison in C and derived languages. 在最后一种情况下,条件是(p = malloc(50)) ,它完全等同于p = malloc(50)但后者是高度可疑的,因为已经提到过在C中执行赋值而不是比较的常见错误语言。 Note that this is not only about suspicious compilers but also humans reading the code and looking at the potential error. 请注意,这不仅涉及可疑编译器,还涉及人们阅读代码并查看潜在错误。

The redundant parentheses are simply a means to tell the readers and the compiler that this assignment is definitely intentional and that it's not an occurence of that common bug. 冗余括号只是一种告诉读者和编译器的方法,这种分配绝对是有意的,并且不是那种常见错误的发生。

The code shouldn't "refuse" to compile unless you have -Werror . 除非你有-Werror否则代码不应该“拒绝”编译。 If you have warnings enabled, it might tell you: 如果您启用了警告,它可能会告诉您:

warning: suggest parentheses around assignment used as truth value [-Wparentheses] while (*dest++ = *src++) 警告:建议用作真值的括号括号[-Wparentheses] while (*dest++ = *src++)

Specifically, the GCC docs say this about the purpose of the warning: 具体来说, 海湾合作委员会的文件说这个警告的目的是:

Warn if parentheses are omitted in certain contexts, such as when there is an assignment in a context where a truth value is expected, or when operators are nested whose precedence people often get confused about. 如果在某些上下文中省略括号,则发出警告,例如在预期真值的上下文中存在赋值,或者当嵌套运算符时,优先级常常会让人感到困惑。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM