Short-circuiting and readability - c

In this line
if ((last_search == NULL) || (last_search != NULL && total_results != 0))
I know that C's short-circuit evaluation rules say that only if last_search is not null will it try and evaluate the right-hand side of ||, hence it's equivalent to writing
if ((last_search == NULL) || (total_results != 0))
and I was advised to use the later by someone, but still isn't the former more readable? Also won't the compiler optimize out the redundant last_search != NULL?

This is subjective, but no, the first variant is not more readable because there's more to read. The most readable code (and the least buggy!) is that which does not exist. Just think what would happen if you wanted to check 3 or 4 conditions at once.
And here's another counterexample: would you write code like this?
if (number < 0) {
}
else if(number >= 0) {
// why not just "else"?
}
As for performance: the compiler would probably optimize the redundant call away, but undoing the performance degradation does not help with the readability degradation.

No it's not. The second one is a lot more readable. Why would you keep the redundant check in there, regardless of whether the compiler will optimize it away?
The first version tells you that last_search is not NULL because it got there, but if you can't tell that from the first condition (last_search == NULL failed), you've probably got bigger issues than readability.

It is not only the short circuit evaluation that makes it unreadable but also the fact of using superfluous comparisons.
if ( !last_search || total_results)
is much easier to read than anything that you proposed.

Related

Is there some good reason to check equality with bools?

I modified some chip manufacturer example code to remove a bunch of what I thought were stupid boolean comparisons, such as:
if(var == TRUE) → if(var)
if(TRUE == var) → if(var)
if(var != TRUE) → if(!var)
if(FALSE == var) → if(!var)
if(TRUE == var1 || TRUE == var2) → if(var1 || var2)
if(func() != FALSE) → if(func())
if(func() == TRUE) → if(func())
Where:
#define TRUE 1
#define FALSE 0
I thought this would make the code more readable and maybe even allow the compiler to optimize a little better, but the compiled code size increased by 118 bytes.
Am I missing something? These should be logically equivalent, right?
Ah, this is from the top of my head, but:
8051 has an instruction to jump conditioned on a single bit in a register, JB and JNB. If your compiler knows which bit to check, it can use that.
Alternatively, you can check the value in the accumulator being 0 or not 0, JZ, JNZ. But for that to work you might need to put the value on the accumulator first, which might need clearing and moving to that, adding overhead.
If your compiler isn't very old-school, use the built-in but not very standard _Bool or similar "pseudotypes", for which your compiler will work as smart as it can (and probably do what you intended to do).
Not only is it unnecessary, it is a bad idea. Only comparison to FALSE is safe, since any non-zero value is implicitly true, but comparing such a value to TRUE may fail.
You did the right thing. Although you may need to consider maintenance. If the vendor updates this code, you may have to re-apply all your changes. Often it is simpler to live with third-party code as-is; no such code is ever going to confirm to your specific local coding standards or style - probably in moor ways than just this. Live with it or don't use it; certainly do not copy it.
In your own code you'd do better to use stdbool.h and bool, true and false. But you should still avoid explicit tests since it is unnecessary.
What I would avoid is implicit conversions to bool however. So for example a non-null pointer test should be if( ptr != NULL) rather than the common idiom if( ptr ). The 'rule' being that the condition expression should be explicitly Boolean. In your case if var is Boolean then there is no need to test for equality to true/false. Conversely if var is not Boolean, then you should test using the Boolean expressions 0 == var/0 != var.
The advice is largely about code quality, robustness, clarity and maintainability. I doubt that it will have any impact on code generation in any reasonable compiler.

Efficiency of using "AND" or "OR"

Which is better to use && or ||? For example if I need to check if input is between 5 and 27 and divisible by 3, is it better to check as
if((num < 5) || (num > 27) || (num%3 != 0))
{
//skip
}
else
{
//operations
}
OR
if((num >= 5) && (num <= 27) && (num%3 == 0)
{
//operations
}
Unless you are doing this in an extremely tight loop, you will never notice any difference whatsoever.
Most C compilers will rewrite the expression to take advantage of short-circuit evaluation anyhow, so for those compilers the order is irrelevant (for C++ there are exceptions).
If your compiler cannot optimize the Boolean math (very unlikely in a modern compiler), the second form is better because it allows for some terms to be skipped.
From the CPU's perspective, || and && will more likely than not take exactly the same amount of time to complete. From the compiler's perspective, transforming between the two will be a trivial operation -- this is certainly a choice it will make correctly for you. Use whichever is clearest to you.
It is far more important for you to make good use of C's short circuiting to ensure that the branch is determined in as few executed instructions as possible.

Writing conditional statements in c as (value == variable) instead of (variable == value) [duplicate]

This question already has answers here:
What is the difference between these (bCondition == NULL) and (NULL==bCondition)? [duplicate]
(6 answers)
Closed 9 years ago.
I have observed that a lot of coders while writing a condition statement do something like this
if(NULL == Ptr){
//Some code
}
instead of if(Ptr == NULL){ //some code ...
What is a reason behind this coding practice? I belive that it does not change the meaning of the statement in anyway, so why write like this?
Please point me out if I am making a blunder.
The usual reason for doing this, is so if the code is mistakenly written as
if(NULL = Ptr){
//Some code
}
It will be a compile error, rather than just a semantic error.
As ouah and Bo Persson point out, this is largely unnecessary, as modern compilers have reintegrated much of the semantic checking that historically was delegated to a separate lint program.
gcc -Wall -Wextra will tell you the line looks fishy:
test.c:3:2: warning: suggest parentheses around assignment used as truth value
I don't consider it semantically wrong as ouah does, comparison being commutative (even when implemented by subtraction and test for non-zero). But it does make the code less readable, if you intend to read it aloud, perhaps to a review group.
If NULL is-equal-to pointer then
Block comment (some code) end-Block
It reads funny this way. Whereas
If pointer is-equal-to NULL ...
is smoother to the ear.
if(NULL == Ptr)
is equivalent to
if(Ptr == NULL)
as the == operator is commutative. The idea of this form is to trigger a compiler error if the programmer incorrectly wrote NULL = Ptr when he meant NULL == Ptr.
The problem with this approach is IMHO it makes the code less readable and it is semantically incorrect because you want to compare Ptr to NULL and not the opposite.
Moreover any decent compiler with warnings enabled will trigger a warning with if (Ptr = NULL).
It does the same thing, but I find it confusing, since to be consistent, you also need to write
if (0 > a)
instead of
if (a < 0)
which is often confusing, since there is a document or something describing that "a must be less than zero", not "zero must be more than a".

Should 'if' test for '==' or '!='

Is there any particular reason for != to be used more than ==?
I have noticed that != seems more common, but wondered if there was a reason for this.
If you have code like this:
if (a == b)
{
// block 1
}
else
{
// block 2
}
It can be rewritten as:
if (a != b)
{
// block 2
}
else
{
// block 1
}
These two examples do the same thing. Neither is more efficient than the other. If one is used more than the other it may be personal preference.
You should use == or != according to the logical condition you are trying to express. If you care about both the true and false conditions, i.e. both the if and else parts then the net effect of switching (if it's a simple comparison) is just which code needs to appear in which part.
There is a coding style, see (the book) Code Complete's section on Forming Boolean Expressions Positively which suggests that boolean expressions that express something positive are easier to understand than those expressing something negative.
If you only care about the condition when it evaluates to true, e.g. you only care when you have equality (for ==) or do not have equality (for !=) then you'll not require an else section if you pick the correct one.
Most of the time the preference of using != or == will depend on the content:
resultOfOperationOrCall = operationOrCall(...);
if (resultOfOperationOrCall != somePredefinedErrorTypeValue) {
// Normal processing
} else {
// Exception/error processing
}
Here using != is logically clearer than using ==
I prefer != because it's more explicit (and there is less chances to write = as mistake).
As assembly code for both == and != present so no issue of efficient or inefficient code for x86 architecture.So it is up to you .you can use any one of them.
if for some machine if assembly code not available then efficient or inefficient comes it to picture as that is achieved by compiler by performing some additional operation(that is adding additional assembly code).
Its wholly and solely depends on the perception & need of user. I don't see any reason on why would one use != more than ==

What is the difference between if(CONST==variable) or if(variable==CONST)?

Is there a difference in the order of the comparison operator?
#define CONST_VALUE 5
int variable;
...
if ( variable == CONST_VALUE ) // Method 1
...
OR
if ( CONST_VALUE == variable ) // Method 2
...
Is this simply a matter of preference or is there a compelling reason for a particular comparison order?
The reason some people use method 2 is because you'll get a compiler error if you mistype a = in place of the ==.
However, you'll have people (like me) who will still use method 1 because they find it more readable and if there is an error, it will be detected during testing (or, in some cases, static analysis of the code).
The only difference is that ( CONST_VALUE == variable ) makes the common typo ( CONST_VALUE = variable ) impossible to compile.
By comparison, if ( variable = CONST_VALUE ) will result in the compiler thinking you meant to assign CONST_VALUE to 'variable'.
The =/== confusion is a pretty common source of bugs in C, which is why people are trying to work around the issue with coding conventions.
Of course, this won't save you if you're comparing two variables.
And the question seems to be a duplicate of How to check for equals? (0 == i) or (i == 0)
And here's some more information: http://cwe.mitre.org/data/definitions/481.html
As others mentioned, CONST_VALUE == variable avoids the = typo.
I still do "variable == CONST_VALUE", because I think its more readable and when I see something like:
if(false == somevariable)
my bloodpressure goes up.
The first variant
if (variable == CONST_VALUE)
is better, because it is more readable. It follows the convention (also used in mathematics) that the value that changes most comes first.
The second variant
if (CONST_VALUE == variable)
is used by some people to prevent a mixup of equality checking with the assignment
if (CONST_VALUE = variable)
There are better ways to achieve that, for example enabling and taking heed of compiler warnings.
Others already pointed out the reason. = / == confusion. I prefer the first version because it follows the thought process more closely. Some compiler alleviate the confusion of = and == by giving a warning when it encounters something like
if(a=b)
in this case if you really wanted to do the assignation you're forced to write
if((a=b))
which I would write then as
if( (a=b) != 0)
to avoid the confusion.
This said, we had in our code 1 case where we had a =/== confusion and writing it the other way round wouldn't not have aided as it was a comparison between vars.

Resources