Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

A favorite of mine, in C:

  ASSERT(apples = 1);
  VERIFY(oranges = 2);
(Note the '=' means assignment, not comparison.)

Both are assertion-testers resulting in a core dump if the test fails, but ASSERT is only defined for DEBUG builds.

Since the assignments are to nonzero (true) values, buggy values of 'apples' are silently corrected -- but only during test runs. Buggy values of 'oranges' are always silently corrected.

Hilarity ensued. Afterwards, 'gcc -Wparentheses' became mandatory.



One way to avoid this kind of mistakes is to use Yoda conditions [0]:

    ASSERTS(1 == apples);
If you forget one `=`, it doesn't compile.

[0]: https://en.wikipedia.org/wiki/Yoda_conditions


I don't think learning this is worth it. Using this will not always warn you( complicated expression or variables ) and you still might miss something.

+EDIT: In those occasions when you actually compare to a integer, the expression is so simple that you immediately understand the whole line. In case of an actual typo the compiler will warn you, and the inversion is not needed. Nowadays, there is simply no excuse for a ignored or missed( bad compiler ) warning.

Assignment in an If statement must produce a warning!


Don't understand? If the constant is on the left, then forgetting one of the equals signs will always be an error.


Yes but I think he is saying that if the left/what you compare to is not a constant then it will not warn you (if the type agrees, as it should anyway for a comparison).


If the left is a function call, it will still error out because you can't assign to it.

If you're doing

    if (var1 == var2)
then yoda expressions won't save you, however.


Also, in C++ you can assign to the return value of a function returning a reference.


The word learning in this context doesn't mean understanding this simple trick, which any newbie should grasp immediately.


I like Yoda conditions not only because it protects against the missing "=", but also because often the constant is the shorter side, so reading

    if (42 == some_long_expression_here)
    {
        ...
    }
It is immediately clear that the rest of the line after the two equals signs must be an expression because the curly brace in the beginning of the next line. So folks don't have to bother that much about counting parens.


Well, you won't see 'magic values' in production code, or at least should minimize it


On the other hand, Yoda conditions are - as implied by the name - counterintuitive and, as pointed out below, aren't really necessary when compilers pick up this kind of error anyway. The real problem is that this kind of mistake is even possible in the first place.


This technique was taught to me by Charles Fiterman, before he was at geodesic. And while compilers are a bit better about this nowadays, back then this was a good technique to use.


Don't most compilers give a warning for this sort of thing?


Side fun question: what was Yoda conditions called before Star Wars was in the cinemas?


Maybe it didn't have a name? After all, A New Hope was only released a few years after C, and earlier languages (BCPL, Pascal) used a different expression for assignment (:=), so they didn't suffer from this problem.


Coverity has ASSERT_SIDE_EFFECT for exactly this sort of case.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: