VB6 IIf advantage - if-statement

Is there a performance advantage to using IIf over If?
Other than simply less code... what is the difference between :
If msInitialFloodSection <> Trim$(cboFloodSection.Text) Then
mbFloodSectionChanged = True
Else
mbFloodSectionChanged = False
End If
and
mbFloodSectionChanged = IIf(msInitialFloodSection <> Trim$(cboFloodSection.Text), True, False)

IIf is not an operator or a language construct, it's a function, just like any other function such as Left. It will therefore evaluate all its arguments at all times, whereas with If you will only evaluate the correct branch.
Example:
denominator = 0
value = IIf(denominator = 0, 0, value / denominator)
This will raise Divizion by zero error despite a separate branch exists for denominator being zero.
Regarding performance, what it will do is packing your values into Variants which will require additional ticks, not that much at all, but if we're on performance, then If will be faster because it wouldn't coerce things through Variants and because it will only calculate one of the values, not two.

Related

How does c++ handle 0*(large expression)

Concerning speed, if I need to calculate a large expression, say:
switch1*(large expression 1)+switch2*(large expression 2)
Depending on my input, switch1 can be 0 or 1, as can switch2 be. What would be the quickest for c++ to do, making an if statement or write it down as above?
So, essentially you are asking about Short-Circuit Evaluation, and you are asking whether C++ does it for arithmetic expressions besides boolean expressions.
It is kind of hard to prove a negative, but as far as I know, C++ only does short-circuit evaluation for logical expressions, so there is no equivalent for arithmetic expressions. Also, I can think of plenty of code that would horribly break if arithmetic expressions were being evaluated in a short-circuit fashion, so I don't think that could ever be so.
Theoretically, the compiler could generate code to avoid computing the expression if it could show that it had no side-effects. But in practice, it's unlikely to add code to check if the value is zero because it has no reason to think that it will be.
On the other hand, logical operations (|| and &&) are guaranteed to short-circuit in C++. So you should use them.
result = 0;
if(switch1) {
result += large_expresion_1();
}
if(switch2)
result += large_expression2();
}
But if you are optimising "large expressions" be sure to check whether it's actually quicker to calculate them both then add them in a branchless manner. eg something like
result = ((-(uint64_t)(switch1)) & large_expression_1) + ((-(uint64_t)(switch2)) & large_expression_2);
A bunch of such bithacks are documented here:
https://graphics.stanford.edu/~seander/bithacks.html
Benchmark and separate to that, read the generated assembly language to find out what the compiler is actually doing for (or to) you.
switch1 can be 0 or 1, as can switch2 be
If switch1 and switch2 can really only have values of 0 or 1 then it would be better for them to be booleans rather than integers.
With boolean switches, your statement becomes:
result = (switch1 ? (large expression 1) : 0)
+ (switch2 ? (large expression 2) : 0)
It is the case that in this form, the expressions will be computed even if their result won't be used. A simple and clear way to avoid wasted computation is the obvious one:
result = 0;
if(switch1) {
result += large expression 1;
}
if(switch2) {
result += large expression 2;
}
You could tidy this up by extracting methods, into which you pass the switches:
result = guardedLargeExpression1(switch1, otherparams1)
+ guardedLargeExpression2(switch2, otherparams2);
... with ...
int guardedLargeExpression1(bool switch, foo params) {
if(switch) {
return 0;
}
return large expression(...);
}
You could also do clever stuff with pointers to functions:
int guardedFunctionCall(bool switch, int *functionptr(foo), foo arg) {
if(switch) {
return 0;
}
return (*functionptr)(arg);
}
... which is approaching the kind of thing you'd do in Java when you lazily evaluate code using a Supplier.
Or, since you're in C++ not C, you can do something more OO and actually use the C++ equivalent of Supplier: What is the C++ equivalent of a java.util.function.Supplier?
If depends on the exact conditions. CPU, compiler, the exact expressions.
An if can slow down a program, if if becomes a conditional jump in the assembly code, and the condition cannot be predicted.
If the conditional cannot be predicted, and the "large expressions" are actually simple, it may be faster to do the "multiply-way".
However, if the expressions are slow to calculate, or the if can be branch predicted perfectly (or it doesn't compile to a conditional jump), then I think the if way will be faster.
All in all, you should try both solutions, and check which is faster.

Is there any significance to this return statement?

I was wondering if there was any significance in a part of a code I am seeing that involves
return (num!=0);
where num is an int. And this is the return statement of a boolean function that wants to return TRUE if num != 0, and false if num = 0.
I am not sure if there is an hidden significance to this, but I am not seeing why they cannot just simply write:
return num;
Here is the code I saw:
bool SemClass::cut(int &a, int &b, int &c)
{
int num = 0;
check(a, num);
check(b, num );
check(c, num);
return (num != 0);
}
The value 0 for integral, floating-point, and unscoped enumeration and the null pointer and the null pointer-to-member values become false when returned as a boolean by implicit conversion. Other values such as 1, 2, 3, 4 etc. map to true. This convention was established in original C, via its flow control statements; C didn't have a boolean type at the time.
Implicit conversions: en.cppreference.com/w/cpp/language/implicit_cast
In this case, in C++, writing num and num!=0 are both fine. However, num!=0 might make it more obvious that the method is returning a boolean. Technically, only an integer of value 0 would equate to a boolean false, while all other values would equate to a boolean true. By writing num!=0, It is made explicit that the method would return true if num is not equivalent to 0 and false if it is.
Good practice dictates that if it's a genuine truth value, then you should use a boolean as it makes it very clear to the caller what will be returned. When returning an integer, it could be seen as a code/enum type value.
Therefore, num!= is preferred to num in this case. The brackets are not required however. Some compilers will also issue a warning if you return an integer when the method is supposed to return a boolean.
The author may have written return num, the compiler would generate the exact same binary. Here, the author tries to be explicit and to make as easy as possible to the reader to guess what the function returns.
When a quick reader sees return num knowing that num is an int and the current function returns a bool, (s)he needs to stop for a fraction of a second to a few seconds (depending on its concentration and ease regarding C++) to remember that an integer is implicitly convertible to a boolean with the mapping 0 -> false, anything else -> true. So, why not write that down?
When the quick reader sees return num!=0, (s)he guesses that the current function returns a boolean (it could be otherwise, but it would be suspicious) and comprehend easily what the return value means.
As a rule of thumb, I'd advise to pick the more explicit writing when it does not hurt the reading and when it takes only a few more (or less) characters. Don't forget that you do not write code for the compiler, you write code for the dozens of other developers who works or will work with you(r code). C++ may be less common in 20 years, it would be great if your program could be easily understood not only by gurus but by everyone (I'm generalizing there, not only talking about the implicit boolean conversion).
The author is being (excessively) careful on two counts:
The parentheses are redundant.
Any numeric type in C++ has an implicit conversion to bool: if the number compares to zero then it's false, else it's true.
Personally I prefer the naked return num; as I find that clearer.
(Note that in C, the relational operators return the int types 1 and 0, rather than true and false).

Omit "> 0" in conditional?

I have recently inherited an old project to make some optimization and add new features. In this project I have seen this type of condition all over the code:
if (int_variable)
instead of
if (int_variable > 0)
I have used the first option only with boolean type of variables.
Do you think the first option is a "correct" way to check if a number is positive?
negative numbers evaluate to true also,so you should go with if (int_variable > 0) to check if a number is positive.
No. The first option is a correct way to check if a number is non-zero.
Any non-zero value will be considered true, so your version with > is a bit sketchy if the variable truly is int, i.e. signed. For clarity I prefer to make that explicit in many cases, i.e. write
if (int_variable != 0)
This is perhaps a bit convoluted (basically computing a Boolean where one can be automatically inferred), I would never use if (bool_variable == true) for instance but I think the integer case makes the test clearer. Reading the two cases out loud works way better for the integer.
if (int_variable) has the same meaning as if (int_variable != 0).
This is not the same as if (int_variable > 0) unless you otherwise know that the value will never be negative.
When using an integer value as a truth value in C, zero yields false while any non-zero value yields true.
In your case, assuming int_variable is signed, (int_variable) is not equivalent to (int_variable > 0) since int_variable being negative will yield true and false, respectively.
So
if (int_variable) { … }
is not a correct way of checking whether int_variable is positive.
In C any expression which evaluates to integer 0 or a null pointer is considered false. Anything else is true.
So basically something like
int i = ...;
if ( i )
Test if i is 0. However, if i is negative, the condition will also be true, so this is no replacement for i > 0. Unless i is unsigned. Simply because they cannot be negative. But your compiler may warn about such constructs as they often show a wrong concept.
Coming to coding style, if ( i ) is bad style if you are really comparing to the value 0. You better compare explicitly: if ( i != 0 ). However, if i contains some boolean result, you should use a "speaking" name (e.g. isalpha('A') to use a ctypes.h function instead of a variable) and do not compare. Compare the readbility:
char ch = ...;
if ( isalpha(ch) )
if ( isalpha(ch) != 0 )
For the latter you have to think a second about the comparison - unnecessarily.

is check required in this situation

In C++ I read a coding guideline as "check return value in If control statement"
Like,
if(TRUE == fun1())
{
//Statements
}
When "fun1" returns True, internally in "if" statement it will be compared with “true”.
Is it necessary to compare externally.?
Is this a good practice or is this style of coding decreases performance.?
Comparing to TRUE is never a good idea.
If fun1 returns a BOOL, than its value is in fact an int and can have any int value. TRUE is just 1, FALSE is 0. But there are a lot of other values for an int. Comparing to FALSE is always save!
In a lot of cases. Functions return "something" and that should mean "TRUE" (!=0) as long as it is different from 0!
As long as you have a bool return value you can compare to true and false and it will always work.
It depends on the style, but I never use an expression to compare to a TRUE value (meaning not 0, not false). I always write the condition without an operator in the if statement. And it has the meaning for me "If fun1 is something" or "If fun1 succeeded"
if (fun1())
{
//Statements
}
In our company this is the normal coding style. And if we want to check the reverse. "If fun1 fails"
if (!fun1())
{
}
With modern compilers and processors there is no real speed impact.
Depends on the return type of fun1 and the type of TRUE.
If TRUE is true and fun1 returns bool, it doesn't decrease performance, because it does exactly what the if does itself. So it's just no-op clutter.
With other types, it looks dangerous and could even be wrong. Imagine a legacy-style function which returns int and is documented to return 0 on failure and a non-zero value on success (quite a few C standard library functions are like that). Then, let's say TRUE is true or 1. In this case, the function returning 2 (a perfectly valid non-zero value) would actually fail the condition!
So unless the types and values are so perverted that TRUE is 0 (which is not the case with MFC), I'd say it's actually harmful to compare with it.

How far does GCC's __builtin_expect go?

While answering another question I got curious about this. I'm well aware that
if( __builtin_expect( !!a, 0 ) ) {
// not likely
} else {
// quite likely
}
will make the "quite likely" branch faster (in general) by doing something along the lines of hinting to the processor / changing the assembly code order / some kind of magic. (if anyone can clarify that magic that would also be great).
But does this work for a) inline ifs, b) variables and c) values other than 0 and 1? i.e. will
__builtin_expect( !!a, 0 ) ? /* unlikely */ : /* likely */;
or
int x = __builtin_expect( t / 10, 7 );
if( x == 7 ) {
// likely
} else {
// unlikely
}
or
if( __builtin_expect( a, 3 ) ) {
// likely
// uh-oh, what happens if a is 2?
} else {
// unlikely
}
have any effect? And does all of this depend on the architecture being targeted?
Did you read the GCC documentation?
Built-in Function: long __builtin_expect (long exp, long c)
You may use __builtin_expect to provide the compiler with branch
prediction information. In general, you should prefer to use actual
profile feedback for this (-fprofile-arcs), as programmers are
notoriously bad at predicting how their programs actually perform.
However, there are applications in which this data is hard to collect.
The return value is the value of exp, which should be an integral
expression. The semantics of the built-in are that it is expected that
exp == c. For example:
if (__builtin_expect (x, 0))
foo ();
indicates that we do not expect to call foo, since we expect x to be zero. Since you are limited to integral expressions for exp, you should use constructions such as
if (__builtin_expect (ptr != NULL, 1))
foo (*ptr);
when testing pointer or floating-point values.
To explain this a bit... __builtin_expect is specifically useful for communicating which branch you think the program's likely to take. You ask how the compiler can use that insight - well, consider this code:
if (x == 0)
return 10 * y;
else
return 39;
In machine code, the CPU can typically be asked to "goto" another line (which takes time, and depending on the CPU may prevent other execution optimisations - i.e. beneath the level of machine code - for example, see the Branches heading under http://en.wikipedia.org/wiki/Instruction_pipeline), or to call some other code, but there's not really an if/else concept where both true and false code are equal... you have to branch away to find the code for one or the other. The way that's done is basically, in pseudo-code:
test whether x is 0
if it was goto else_return_39
return 10 * y
else_return_39:
return 39
Given most CPUs are slower following the goto down to the else_return_39: label than to just fall through to return 10 * y, code for the "true" branch will be reached faster than for the false branch. Of course, the machine code could test whether x is not 0, put the "false" code (return 39) first and thereby reverse the performance characteristics.
This is what __builtin_expect controls - you can tell the compiler to put the true or the false branch where less branching is needed to reach it, thereby getting a tiny performance boost.
But does this work for a) inline ifs, b) variables and c) values other than 0 and 1?
a) Whether the surrounding function is inlined or not doesn't change the need for branching where the if statement appears (unless the optimiser sees the condition the if statement tests is always true or false and only one branch could never run). So, it's equally applicable to inlined code.
[ Your comment shows you were interested in conditional expressions - a ? b : c - I'm not sure - there's a disputed answer to that question at https://stackoverflow.com/questions/14784481/can-i-use-gccs-builtin-expect-with-ternary-operator-in-c that might prove insightful one way or the other, or the basis for further exploration ]
b) variables - you postulated:
int x = __builtin_expect( t / 10, 7 );
if( x == 7 ) {
That won't work - the compiler's not obliged to associate such expectations with variables and remember them the next time an if is seen. You can verify this (as I did for gcc 3.4.4) using gcc -S to produce assembly language output: the assembly doesn't change regardless of the expected value.
c) values other than 0 and 1
It works for integral (long) values, so yes. The last paragraph of the documentation quoted above address this, specifically:
you should use constructions such as
if (__builtin_expect (ptr != NULL, 1))
foo (*ptr);
when testing pointer or floating-point values.
Why? Well, if the pointer type is larger than long, then calling __builtin_conversion(long, long) would effectively slice off some of the less-significant bits for the test, and fail to incorporate the (high-order) rest in the test. Similarly, floating point values might be larger than a long, and the conversion not produce the result you expect. By using a boolean expression such as ptr != NULL (given true converts to 1 and false to 0) you're sure to get intended results.
But does this work for a) inline ifs, b) variables and c) values other than 0 and 1?
It works for an expression context that is used to determine branching.
So, a) Yes. b) No. c) Yes.
And does all of this depend on the architecture being targeted?
Yes!
It leverages architectures that use instruction pipelining, which allow a CPU to begin working on upcoming instructions before the current instruction has been completed.
(if anyone can clarify that magic that would also be great).
("Branch prediction" complicates this description, so I'm intentionally omitting it)
Any code resembling an if statement implies that an expression may result in the CPU jumping to a different location in the program. These jumps invalidate what's in the CPU's instruction pipeline.
__builtin_expect allows (without guarantee) gcc to try to assemble the code so the likely scenario involves fewer jumps than the alternate.