Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<h2>Preamble</h2> <p>Note that this answer is about C++ (I started writing this answer before the tag "C" was added).</p> <p>Still, after reading Jens Gustedt's comment, I realized it was not the first time I wrote this kind of answer. Truth is, this question is a duplicate of another, to which I gave the following answer:</p> <p><a href="https://stackoverflow.com/questions/399792/inadvertent-use-of-instead-of/400644#400644"><a href="https://stackoverflow.com/questions/399792/inadvertent-use-of-instead-of/400644#400644">Inadvertent use of = instead of ==</a></a></p> <p>So, I'll shamelessly quote myself here to add an important info: <b><code>if</code> is not about comparison. It's about evaluation.</b></p> <p>This difference is very important because it means anything can be inside the parentheses of a <code>if</code> as long as it can be evaluated to a boolean. <b>And this is a good thing.</b></p> <p>Now, limiting the language by forbidding <code>=</code>, where all other operators are authorized, is a dangerous exception for the language, an exception whose use would be far from certain, and whose drawbacks would be numerous indeed.</p> <p>For those who are unneasy with the <code>=</code> typo, then there are solutions (see <b>Alternatives</b> below...).</p> <h2><a href="https://stackoverflow.com/questions/399792/inadvertent-use-of-instead-of/400644#400644">About the valid uses of if(i = 0) [Quoted from myself]</a></h2> <p>The problem is that you're taking the problem upside down. The "if" notation is not about comparing two values like in some other languages.</p> <p>The C/C++ <code>if</code> instruction waits for any expression that will evaluate to either a boolean, or a null/non-null value. This expression can include two values comparison, and/or can be much more complex.</p> <p>For example, you can have:</p> <pre><code>if(i &gt;&gt; 3) { std::cout &lt;&lt; "i is less than 8" &lt;&lt; std::endl } </code></pre> <p>Which proves that, in C/C++, the if expression is not limited to == and =. Anything will do, as long as it can be evaluated as true or false (C++), or zero non-zero (C/C++).</p> <h2>About valid uses</h2> <p>Back to the non-quoted answer.</p> <p>The following notation:</p> <pre><code>if(MyObject * p = findMyObject()) { // uses p } </code></pre> <p>enables the user to declare and then use p inside the if. It is a syntactic sugar... But an interesting one. For example, imagine the case of an XML DOM-like object whose type is unknown well until runtime, and you need to use RTTI:</p> <pre><code>void foo(Node * p_p) { if(BodyNode * p = dynamic_cast&lt;BodyNode *&gt;(p_p)) { // this is a &lt;body&gt; node } else if(SpanNode * p = dynamic_cast&lt;SpanNode *&gt;(p_p)) { // this is a &lt;span&gt; node } else if(DivNode * p = dynamic_cast&lt;DivNode *&gt;(p_p)) { // this is a &lt;div&gt; node } // etc. } </code></pre> <p>RTTI should not be abused, of course, but this is but one example of this syntactic sugar.</p> <p>Another use would be to use what is called C++ Variable Injection. In Java, there is this cool keyword:</p> <pre><code>synchronized(p) { // Now, the Java code is synchronized using p as a mutex } </code></pre> <p>In C++, you can do it, too. I don't have the exact code in mind (nor the exact DDJ's article where I discovered it), but this simple define should be enough for demonstration purposes:</p> <pre><code>#define synchronized(lock) \ if (auto_lock lock_##__LINE__(lock)) synchronized(p) { // Now, the C++ code is synchronized using p as a mutex } </code></pre> <p>(Note that this macro is quite primitive, and should not be used as is in production code. The real macro uses a <code>if</code> and a <code>for</code>. See <b>sources</b> below for a more correct implementation).</p> <p>This is the same way, mixing injection with <code>if</code> and <code>for</code> declaration, you can declare a primitive foreach macro (if you want an industrial-strength foreach, use boost's).</p> <h2>About your typo problem</h2> <p>Your problem is a typo, and there are multiple ways to limit its frequency in your code. The most important one is to make sure the left-hand-side operand is constant.</p> <p>For example, this code won't compile for multiple reasons:</p> <pre><code>if( NULL = b ) // won't compile because it is illegal // to assign a value to r-values. </code></pre> <p>Or even better:</p> <pre><code>const T a ; // etc. if( a = b ) // Won't compile because it is illegal // to modify a constant object </code></pre> <p>This is why in my code, <code>const</code> is one of the most used keyword you'll find. Unless I REALLY want to modify a variable, it is declared <code>const</code> and thus, the compiler protects me from most errors, including the typo error that motivated you to write this question.</p> <p>But is there a case where the warning should be ignored because it's a good way to use this "feature"? I don't see any code clarity reason possible so is there a case where its useful?</p> <h2>Conclusion</h2> <p>As shown in the examples above, there are multiple valid uses for the feature you used in your question.</p> <p>My own code is a magnitude cleaner and clearer since I use the code injection enabled by this feature:</p> <pre><code>void foo() { // some code LOCK(mutex) { // some code protected by a mutex } FOREACH(char c, MyVectorOfChar) { // using c } } </code></pre> <p>... which makes the rare times I was confronted to this typo a negligible price to pay (and I can't remember the last time I wrote this type without being caught by the compiler).</p> <h2>Interesting sources</h2> <p>I finally found the articles I've had read on variable injection. Here we go !!!</p> <ul> <li><a href="http://www.drdobbs.com/184401723?pgno=6" rel="nofollow noreferrer">http://www.drdobbs.com/184401723?pgno=6</a></li> <li><a href="http://www.drdobbs.com/184401728" rel="nofollow noreferrer">http://www.drdobbs.com/184401728</a></li> <li><a href="http://www.drdobbs.com/184401752" rel="nofollow noreferrer">http://www.drdobbs.com/184401752</a></li> </ul> <h2>Alternatives</h2> <p>If one fears being victim of the <code>=</code>/<code>==</code> typo, then perhaps using a macro could help:</p> <pre><code>#define EQUALS == #define ARE_EQUALS(lhs,rhs) (lhs == rhs) int main(int argc, char* argv[]) { int a = 25 ; double b = 25 ; if(a EQUALS b) std::cout &lt;&lt; "equals" &lt;&lt; std::endl ; else std::cout &lt;&lt; "NOT equals" &lt;&lt; std::endl ; if(ARE_EQUALS(a, b)) std::cout &lt;&lt; "equals" &lt;&lt; std::endl ; else std::cout &lt;&lt; "NOT equals" &lt;&lt; std::endl ; return 0 ; } </code></pre> <p>This way, one can protect oneself from the typo error, without needing a language limitation (that would cripple language), for a bug that happens rarely (i.e. almost never, as far as I remember it in my code)</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload