Inadvertent use of = instead of ==

2019-01-07 21:46发布

It seems that

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

instead of

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

is a root of many evils.

Why don't all compilers mark it as error instead of a configurable warning?

I'm interested in finding out cases where the construct if (x=y) is useful.

28条回答
手持菜刀,她持情操
2楼-- · 2019-01-07 21:50

Simple answer: An assignment operation, such as x=y, has a value, which is the same as the newly assigned value in x. You can use this directly in a comparison, so instead of

x = y; if (x) ...

you can write

if (x = y) ...

It is less code to write(and read), which is sometimes a good thing, but nowadays most people agree that it should be written in some other way to increase readability. For example like this:

if ((x = y) != 0) ...

Here is a realistic example. Assume you want to allocate some memory with malloc, and see if it worked. It can be written step by step like this:

p = malloc(4711); if (p != NULL) printf("Ok!");

The comparison to NULL is redundant, so you can rewrite it like this:

p = malloc(4711); if (p) printf("Ok!");

But since the assignment operation has a value, which can be used, you could put the entire assignment in the if condition:

if (p = malloc(4711)) printf("Ok!");

This does the same thing, but is more concise.

查看更多
smile是对你的礼貌
3楼-- · 2019-01-07 21:50

Try viewing

if( life_is_good() )
    enjoy_yourself();

as

if( tmp = life_is_good() )
    enjoy_yourself();
查看更多
太酷不给撩
4楼-- · 2019-01-07 21:50

The compiler won't flag it as an error because it is valid C/C++. But what you can do (at least with Visual C++) is turn up the warning level so that it flags it as a warning and then tell the compiler to treat warnings as errors. This is a good practice anyway so that developers don't ignore warnings.

If you had actually meant = instead of == then you need to be more explicit about it. e.g.

if ((x = y) != 0)

Theoretically, you're supposed to be able to do this:

if ((x = y))

to override the warning, but that doesn't seem to always work.

查看更多
Explosion°爆炸
5楼-- · 2019-01-07 21:54

Standard C idiom for iterating:

list_elem* curr;
while ( (curr = next_item(list)) != null ) {
  /* ... */
}
查看更多
再贱就再见
6楼-- · 2019-01-07 21:54

I, personally, consider this the most useful example.

Say that you have a function read() that returns the number of bytes read, and you need to use this in a loop. It's a lot simpler to use

while((count = read(foo)) > 0) {
    //Do stuff
}

than to try and get the assignment out of the loop head, which would result in things like

while(1) {
    count = read(foo);
    if(!(count > 0))
        break;
    //...
}

or

count = read(foo);
while(count > 0) {
    //...
    count = read(foo);
}

The first construct feels awkward, and the second repeats code in an unpleasant way.

Unless, of course, I've missed some brilliant idiom for this...

查看更多
可以哭但决不认输i
7楼-- · 2019-01-07 21:55
 if ((k==1) || (k==2)) is a conditional
 if ((k=1)  || (k=2) ) is BOTH a conditional AND an assignment statement
  • Here's the explanation *

Like most languages, C works inner-most to outermost in order by operator precedence.

First it tries to set k to 1, and succeeds.

Result: k = 1 and Boolean = 'true'

Next: it sets k to 2, and succeeds.

Result: k = 2 and Boolean = 'true'

Next: it evaluates (true || true)

Result: k still = 2, and Boolean = true

Finally, it then resolves the conditional: If (true)

  Result: k = 2 and the program takes the first branch.

In nearly 30 years of programming I have not seen a valid reason for using this construct, though if one exists it probably has to do with a need to deliberately obfuscate your code.

When one of our new people has a problem, this is one of the things I look for, right along with not sticking a terminator on a string, and copying a debug statement from one place to another and not changing the '%i to '%s' to match the new field they are dumping.

This is fairly common in our shop because we constantly switch between C and Oracle PL/SQL; if( k = 1) IS the correct syntax in PL/SQL.

查看更多
登录 后发表回答