I am rewriting some C++ code, I have the following
if (ConfidenceBias.value > 0) *normalInfo = tree.setDataField(NormalSigs(), *samples, *sampleData, density, pointWeightSum, ConversionAndBiasFunction);
else *normalInfo = tree.setDataField(NormalSigs(), *samples, *sampleData, density, pointWeightSum, ConversionFunction); ThreadPool::Parallel_for(0, normalInfo->size(), [&](unsigned int, size_t i) { (*normalInfo)[i] *= (Real)-1.; });
I assume that this is equivalent to
if (ConfidenceBias.value > 0)
{
*normalInfo = tree.setDataField(NormalSigs(), *samples, *sampleData, density, pointWeightSum, ConversionAndBiasFunction);
}
else
{
*normalInfo = tree.setDataField(NormalSigs(), *samples, *sampleData, density, pointWeightSum, ConversionFunction);
}
ThreadPool::Parallel_for(0, normalInfo->size(), [&](unsigned int, size_t i) { (*normalInfo)[i] *= (Real)-1.; });
but there is a slight conern that the compiler is interpreting the original as
if (ConfidenceBias.value > 0)
{
*normalInfo = tree.setDataField(NormalSigs(), *samples, *sampleData, density, pointWeightSum, ConversionAndBiasFunction);
}
else
{
*normalInfo = tree.setDataField(NormalSigs(), *samples, *sampleData, density, pointWeightSum, ConversionFunction);
ThreadPool::Parallel_for(0, normalInfo->size(), [&](unsigned int, size_t i) { (*normalInfo)[i] *= (Real)-1.; });
}
I cannot find a reference to what the VSVC compiler does anywhere. Which is it?
AFAIK your assumption about the code is correct.
For most languages I am ware of only one statement or a compound-statement (e.g. braces) will be executed on the condition.
The
ThreadPool::Parallel_for(0, normalInfo->size(), [&](unsigned int, size_t i) { (*normalInfo)[i] *= (Real)-1.; });
line is really really oddly hidden after the condition and I would assume this a code smell because it makes code hard to read, understand and debug.
Edit because I like complete answers: Also you actually do not need to know what VS C++ compiler is going to do here because this is defined. See Alex Allain's post about this.
Refer to the MSDN docs for this as well: https://learn.microsoft.com/en-US/cpp/cpp/statements-cpp?view=vs-2019
https://learn.microsoft.com/en-US/cpp/cpp/if-else-statement-cpp?view=vs-2019
states
Controls conditional branching. Statements in the if-block are
executed only if the if-expression evaluates to a non-zero value (or
TRUE). If the value of expression is nonzero, statement1 and any other
statements in the block are executed and the else-block, if present,
is skipped. If the value of expression is zero, then the if-block is
skipped and the else-block, if present, is executed. Expressions that
...
To understand this check the definition of statement:
Expression statements cause expressions to be evaluated. No transfer
of control or iteration takes place as a result of an expression
statement.
The syntax for the expression statement is simply Syntax
[expression ] ;
and here is the compound statement block definition
A compound statement consists of zero or more statements enclosed in
curly braces ({ }). A compound statement can be used anywhere a
statement is expected. Compound statements are commonly called
"blocks." Syntax
{ [ statement-list ] }
Verdict: Your assumption was valid, your fear unfounded :)
Related
I want to be able to generate a boolean condition during the runtime based on the states of some variables. My task looks simple at first. I have a large if () else if () statement what needs to determine if the number is in a certain range. It then does something depending on whether that number is inside that range.
Here's pseudocode to demonstrate what I want:
void fun(int num, int offset = 0) {
if (0...60) {
// do something
} else if (60...180) {
// do something else
} else if (180...240) {
} else if (240...360) {
}
}
The first if statement should work like this:
if (0 >= num && num <= 20) {
// do something
}
The caveat here is that in addition to int num, there is another parameter passed in, which I call the offset. The structure of the code here, including the do something inside the { } is the same. The only things that need to change are are ranges, based on the value of the offset. By the way, this is not a default parameter here, it is just pseudocode demonstrating what the value of int offset was passed in.
void fun(int num, int offset = 120) {
if (120...180) {
// do something
} else if (180...300) {
// do something else
} else if (300...360) {
} else if (360...120) {
}
}
That last else if () statement has been giving me some trouble.
} else if (360...120) {
}
What I'm actually trying to write here is:
} else if (num >= 360 || num <= 120) {
}
The reason for this is that my int num may have a value > 360. However, in that case for the purpose of my application it has to "wrap around" and be treated as a value 0...120.
This is for a mathematical application here. Whenever you have int num > 360, you go around the full circle and you end back at 0 where you started. So that is the effect which I want to achieve.
I don't want to write extra functions. I want my code to be generic because many different values for int num and int offset may be passed into my function. I want to generate the necessary conditions during the runtime based on the value of int offset.
The main problem here is that in the first situations, when int offset = 0 my condition is
} else if (240 >= num && num <= 360) {
}
However, for a different offset we wrap around and so I have to change the format of the entire condition! For example, when int offset = 120, as shown above:
} else if (num >= 360 || num <= 120) {
}
The problem is that in the first situation I had the && in the last else if (), but now I have the || to convey the same meaning. What I'm looking for is a way to be able to manipulate the operators inside the conditional statements as mere chars in a string, then "paste" the completed condition into the if () statements during the runtime!
What's even worse is that this "wrapping around" can occur inside any one of the if () statements, not just the last one. It is based on the value of the offset.
I can't use preprocessor tricks, because I want this to work during the runtime. Maybe it is possible to use function pointers or something for this, but I don't know how to do that. Please note that the ... above is not real C++ code, it is pseudocode! I'm aware that there is a "range-based" switch statement in C++, but I can't use that because of the "wrapping around" property mentioned above.
I have a condition like the following where I just want to have the second bool be the trigger for a single time, since this condition is invoked relatively often I don't like the idea of doing the assignment of it being false every time the condition is true so, I tried to take advantage of the order of logical AND and OR and the post increment operator. But it appears to work don't do what I expected it to do. So is there a way to make a post state switch for this line?
where firstTitleNotSet is:
bool firstTitleNotSet;
if (titleChangedSinceLastGet() || (p_firstTitleNotSet && p_firstTitleNotSet++))
The idea is that the first part is the primary trigger and the second is the trigger that only has to trigger the first time.
While I easily could do
if (titleChangedSinceLastGet() || p_firstTitleNotSet)
{
firstTitleNotSet = false;
//...
}
I don't like this as it is reassigning false when ever the conditional block is invoked.
So is there some way of "post change" the value of a bool from true to false? I know that this would work the other way around but this would negate the advantage of the method most time being the true trigger and therefor skipping the following check.
Note: The reasons for me making such considerations isntead of just taking the second case is, that this block will be called frequently so I'm looking to optimize its consumed runtime.
Well, you could do something like:
if (titleChangedSinceLastGet() ||
(p_firstTitleNotSet ? ((p_firstTitleNotSet=false), true):false))
An alternative syntax would be:
if (titleChangedSinceLastGet() ||
(p_firstTitleNotSet && ((p_firstTitleNotSet=false), true)))
Either one looks somewhat ugly. Note, however, that this is NOT the same as your other alternative:
if (titleChangedSinceLastGet() || p_firstTitleNotSet)
{
p_firstTitleNotSet = false;
//...
}
With your proposed alternative, pontificate the fact that p_firstTitleNotSet gets reset to false no matter what, even if the conditional was entered because titleChangedSinceLastGet().
A more readable way than the assignment inside a ternary operator inside an or inside an if would be just moving the operations to their own statements:
bool needsUpdate = titleChangedSinceLastGet();
if(!needsUpdate && firstTitleSet)
{
needsUpdate = true;
firstTitleSet = false;
}
if(needsUpdate)
{
//...
}
This is likely to produce very similar assembly than the less readable alternative proposed since ternary operators are mostly just syntactic sugar around if statements.
To demonstrate this I gave GCC Explorer the following code:
extern bool first;
bool changed();
int f1()
{
if (changed() ||
(first ? ((first=false), true):false))
return 1;
return 0;
}
int f2()
{
bool b = changed();
if(!b && first)
{
b = true;
first = false;
}
return b;
}
and the generated assembly had only small differences in the generated assembly after optimizations. Certainly have a look for yourself.
I maintain, however, that this is highly unlikely to make a noticeable difference in performance and that this is more for interest's sake.
In my opinion:
if(titleChangedSinceLastUpdate() || firstTitleSet)
{
firstTitleSet = false;
//...
}
is an (at least) equally good option.
You can compare the assembly of the above functions with this one to compare further.
bool f3()
{
if(changed() || first)
{
first = false;
return true;
}
return false;
}
In this kind of situation, I usually write:
bool firstTitleNotSet = true;
if (titleChangedSinceLastGet() || firstTitleNotSet)
{
if (firstTileNotSet) firstTitleNotSet = false;
//...
}
That second comparison will likely be optimized by the compiler.
But if you have a preference for a post-increment operator:
int iterationCount = 0;
if (titleChangedSinceLastGet() || iterationCount++ != 0)
{
//...
}
Note that this will be a problem if iterationCount overflows, but the same is true of the bool firstTitleNotSet that you were post-incrementing.
In terms of code readability and maintainability, I would recommend the former. If the logic of your code is sound, you can probably rely on the compiler to do a very good job optimizing it, even if it looks inelegant to you.
That should work:
int firstTitleSet = 0;
if (titleChangedSinceLastGet() || (!firstTitleSet++))
If you wish to avoid overflow you can do:
int b = 1;
if (titleChangedSinceLastGet() || (b=b*2%4))
at the first iteration b=2 while b=0 at the rest of them.
I'm getting a C4702: unreachable code warning in a for loop; the strange thing is that - by breaking apart the components inside the parens - the warning points to the increment part. Here's a sample program that demonstrates this error:
int main()
{
int foo = 3;
for (int i = 0;
i < 999;
i++) // warning on this line
{
if (foo == 4);
{
break;
}
}
return 0;
}
I can't figure out what's wrong with this line, because the for loop looks very straight-forward.
You have a stray semicolon in your if-statement:
if (foo == 4);
Recall that for loops have the following structure:
for (initialisation; condition; increment/decrement)
statement
Execution will proceed in the following order:
initialisation
condition; if false then end
statement
increment/decrement
Go to step 2
If the compiler is warning about the increment/decrement being unreachable, it means that something before it is causing execution to always skip it - in this case, the stray semicolon causes the break to always execute, jumping out of the loop prematurely.
for (int i = 0;
i < 999;
i++) // warning on this line
{
if (foo == 4);
{
break;
}
}
This is same as
for (int i = 0;
i < 999;
)
{
if (foo == 4);
{
break;
}
i++; /* Note the increment here */
}
So anyways you are going to break because of the if(foo == 4); so i++ is not reachable
The problem (i.e. the unintended ;) is already described in two answers.
I just like to add that you should take a look at your compiler options setting. Many compilers can detect such "strange looking" code and give you a warning. For instance:
Warning: "empty body in an 'if' statement"
Further the compiler can be configured to treat all warnings as errors.
In other words - the compiler options can often help you finding "unintended code" so that you avoid wasting time.
BTW - the eclipse editor can even give a "suspicious semicolon" warning as soon as you type such an if-statement.
In the following for-loop, I don't do anything if conditionA, conditionB, and conditionC all evaluate to true.
for (int i = 0; i < imax; ++i) {
bool conditionA;
// evaluate conditionA
bool conditionB;
// evaluate conditionB
bool conditionC;
// evaluate conditionC
if (conditionA && conditionB && conditionC) continue;
// do something
}
If conditonA evaluates to false, it becomes unnecessary to evaluate conditionB and conditionC. So it seems that I can speed up the loop by writing it in the following way.
for (int i = 0; i < imax; ++i) {
bool conditionA;
// evaluate conditionA
if (conditionA) {
bool conditionB;
// evaluate conditionB
if (conditionB) {
bool conditionC;
// evaluate conditionC
if (conditionC) continue;
}
}
// do something
}
Now this looks ugly and is not understood at first glance. It seems that using the infamous goto the code becomes much more elegant:
for (int i = 0; i < imax; ++i) {
bool conditionA;
// evaluate conditionA
if (!conditionA) goto doSomething;
bool conditionB;
// evaluate conditionB
if (!conditionB) goto doSomething;
bool conditionC;
// evaluate conditionC
if (conditionC) continue;
doSomething:
// do something
}
Does this work as a method for speeding up the loop or is the compiler smart enough that the first version of the code is actually as fast as the second and third version? In case it isn't, is there a better alternative than using goto?
I would move the evaluation of the conditions into separate functions and then do:
for (int i = 0; i < imax; ++i) {
if (conditionA() && conditionB() && conditionC()) continue;
// do something
}
If conditionA returns false, conditionB will never be called, and so on.
This will also make your function shorter and more concise, dividing responsibilities up among other functions.
If you have no good reason for doing an "early exit" like that, you can avoid using continue altogether:
for (int i = 0; i < imax; ++i) {
if (!(conditionA() && conditionB() && conditionC())) {
// do something
}
}
Or use De Morgan's law to get !conditionA() || !conditionB() || !conditionC - whichever you prefer.
Before you try to speed something up, consult your profiler if the loop is really the bottleneck. If it is not, leave the code readable and maintainable (as opposed to a maybe slightly faster, maybe slower but surely errorprone and unreadable mess) and leave it to your compiler's capability to speed things up.
If the loop is the bottleneck, try whatever comes to mind, profile it, and compare the results. Nobody can surely say what your compiler might optimize away.
Never trust anyone but your profiler when it comes to micro performance optimizations.
Compilers are different in what they optimize and how they optimize it, and humans are particularly bad in predicting the savings of those optimizations.
However, if the conditions are not too complicated, I bet the compiler will optimize the boolean variables away anyways and leave you with something like
for (int i = 0; i < imax; ++i) {
if(evalConditionA() && evalConditionB() && evalConditionC())
continue;
doSomething:
}
What you always can do is asess the probabilities to any of the conditions to become false and put the one first that is most likely to trigger short circuit evaluation, so the others wont need to be evaluated so often.
well, as always, if you're wondering about performances, just do a benchmark. Otherwise, I think the best solution really depends on your context. For example your first solution is the best if you can make your conditions in the valuation or as separate functions (or worst case as macros):
for (int i = 0; i < imax; ++i) {
if (! (evaluate conditionA) && (evaluate conditionB) && (evaluate conditionC)) {
// do something
}
}
then lazy evaluation will come to help, and depending on what you do, your compiler may be able to optimize your evaluation with some optimization options.
I also advice you not to use if (condition) continue; but instead if (!condition) { /* do something */ } which helps a better understanding of the algorithm. Don't forget that what you code will be read by someone one day, and that someone may be you!
C++ Compilers (at least Visual Studio) already done what you looking for.
if( bCondA && bCondB && bCondC )
If bCondA == false, the others are not verified.
Should be true for all compilers.
can somebody please tell me the difference between the following two code snippets:
//Code snippet A: Compiles fine
int main()
{
if(int i = 2)
{
i = 2 + 3;
}
else
{
i = 0;
}
}
//Code Snippet B: Doesn't compile :(
int main()
{
if((int i = 2))
{
i = 2 + 3;
}
else
{
i = 0;
}
}
If you notice the diff is just an extra parenthesis at if statement. I am using g++ compiler.Error is "expected primary-expression before âintâ"
Section 6.4 of the C++ standard (draft n2914 of c++0x) has this to say about the format of if statements:
Selection statements choose one of several flows of control.
selection-statement:
if ( condition ) statement
if ( condition ) statement else statement
switch ( condition ) statement
condition:
expression
type-specifier-seq attribute-specifieropt declarator = initializer-clause
type-specifier-seq attribute-specifieropt declarator braced-init-list
That bit at the end means a condition can be either an expression or a decalarator-type construct.
And the minute the parser hits that second parenthesis, it becomes an expression, so no declarations allowed, I'm afraid.
The snippet:
if (int i = 2) { ... } else { ... }
is perfectly valid C++ in which the if section defines an integer i for the duration of the if/else and sets it to 2. It then uses that 2 as the input to the if (2 is always true, being non-zero).
The snippet if((int i = 2)) is no different syntactically to int x = (int i = 2;); if (x) which is not valid C++.
Snippet A is fine - the if condition delares and initialises a variable that can be interpreted as a boolean. The variable is defined within the if and any else blocks.
Snippet B is wrong, because you can't put parentheses around a declaration - you can only put them round expressions. The following is also wrong for the same reason:
int main()
{
int i; // OK
(i = 2); // OK
(int x = 2); // compile error
}
Here is another variant of second snippet error:
int main()
{
int i = (int j = 0);
return 0;
}
You can't declare variables inside ANY expression.
Second () inside for is the same case - you can declare variable i inside for() but not inside nested expression placed into ().
Hope I explained it in proper words, maybe more correct explanation exists. Actually both code fragments are odd.
Both look wrong.
Just because code compiles it doesn't mean it's valid. I'm surprised that the first case is compiling, since it seems like i isn't defined in the else case.
edit: I'm wrong here, definitions in the if condition are valid for that whole if / else statement.