Recently when writing code I encountered a problem. The code was something like this-
if ((var >= min) && (var <= max))
{
return true;
}
Both min and max are macros already defined previously and var is an unsigned integer. I changed the value of min to 0, which generated a warning, unsigned integer >= 0 will always be true.
First I thought to directly remove the first condition to take care of the warning, but my senior refused to do that, as the code is used in not only the project I am working but also other projects, so maybe the value of min may be above 0 in other projects. He suggested me to it like this-
#define min (0-0)
This solved the problem, no warning generated. But I did not understand why did it work? I asked my senior to explain but he said to find out on my own. I searched on google but did not find anything remotely familiar to it.
So can anyone explain to me what happened above?
Thank you in advance.
Answer: Because it seems the compiler doesn`t check the result of expressions.
Just to know: This is a problem. The compiler is correct - unsigned int can not be less than 0. Whatever you pass to this function, that comparison will always be true.
Because you are on work, do what the others tell you, but keep in mind - you are right, that should be removed, because it makes no sense in your current implementation.
Var has to be changed to long long and then everything will be fine! The problem is there!
It is a matter of time, someone to pass negative value to that function and will fail hard. It will make a warning for passing signed value to a function expecting unsigned and the guy will deprecate it to not have warnings ...
#define min (0-0) and #define min (0) would be equivalent for type and value point of view.
It seems that it allows to break the check of your compiler.
Real fix to remove the warning is to handle the case, for example:
if constexpr (min == 0 && std::is_unsigned_v<std::decay_t<decltype(var)>>) {
if (var <= max)
{
return true;
}
} else {
if (var >= min && var <= max)
{
return true;
}
}
which is probably too verbose (and even worse if you do similar stuff for max).
That cure seems not better than the warning :-/
Possible workaround would be to wrap the test in a function,
as I don't think, currently, compilers warn about function returning always true in condition.
so:
// indirect comparison to avoid warning about always true comparison
if (std::less_equal<>{}(min, var) && std::less_equal<>{}(var, max))
{
return true;
}
A macro applies a search and replace before compiling:
So for #define min (0) the code for the compiler will be:
if ((var >= (0)) && (var <= max))
{
return true;
}
And for #define min (0-0) it will be:
if ((var >= (0-0)) && (var <= max))
{
return true;
}
Both var >= 0 and var >= 0-0 are equivalent regarding the types involved in the comparsion.
clang will for example correctly report both with the warning warning: result of comparison of unsigned expression >= 0 is always true [-Wtautological-unsigned-zero-compare].
gcc reports only the (0) case.
Using 0-0 is a bad idea, not only because silencing a warning instead of solving it is a bad idea, but also because that hack might fail in future compiler versions. It just does not solve the problem, but just tricks the compiler. And using macros to define constant also a bad idea.
By usning a constexpr for the constant instead of a macro the case of a >= 0 could have been correctly solved.
Removing var >= min is not necessarily a good idea if the "constant" min exists, as someone could change its value the future. var >= min can only be safely removed the code should not rely on min and should never have a lower bound that is different to the one given by the type of val. So if min has any relevance then the code should be changed to handle the case when it is 0 correctly, so that the compiler is aware that you know that this case could exist.
The #define is a red herring. It only affects situations where min is followed by parentheses, like int x = min (5, 7). It's not a good idea to have a variable with the same name as a macro, but it doesn't hurt you.
Whoever suggested changing the min macro is frankly an idiot. It will fatally break every bit of code that uses the min macro. If you tried that where I work we would have to discuss your further employment, that's how bad it is.
Your problem is that indeed if x is an unsigned variable and min = 0 the comparison x >= 0 will always be true. The compiler gives a warning which in your situation is stupid. A correct change instead if removing the condition would be (x == 0 || x > 0) instead of x >= 0; this will most likely remove the warning.
Related
We know it can in Java and JavaScript.
But the question is, can the condition below ever evaluate to true in C or C++?
if(a==1 && a==2 && a==3)
printf("SUCCESS");
EDIT
If a was an integer.
Depends on your definition of "a is an integer":
int a__(){ static int r; return ++r; }
#define a a__() //a is now an expression of type `int`
int main()
{
return a==1 && a==2 && a==3; //returns 1
}
Of course:
int f(int b) { return b==1&&b==2&&b==3; }
will always return 0; and optimizers will generally replace the check with exactly that.
If we put macro magic aside, I can see one way that could positively answer this question. But it will require a bit more than just standard C. Let's assume we have an extension allowing to use the __attribute__((at(ADDRESS))); attribute, which is placing a variable at some specific memory location (available in some ARM compilers for example, like ARM GCC). Lets assume we have a hardware counter register at the address ADDRESS, which is incrementing each read. Then we could do something like this:
volatile int a __attribute__((at(ADDRESS)));
The volatile is forcing the compiler to generate the register read each time the comparison is performed, so the counter will increment 3 times. If the initial value of the counter is 1, the statement will return true.
P.S. If you don't like the at attribute, same effect can be achieved using linker script by placing a into specific memory section.
If a is of a primitive type (i.e all == and && operators are built in) and you are in defined behavior, and there's no way for another thread to modify a in the middle of execution (this is technically a case of undefined behavior - see comments - but I left it here anyway because it's the example given in the Java question), and there is no preprocessor magic involved (see chosen answer), then I don't believe there is anything way for this to evaluate to true. However, as you can see by that list of conditions, there are many scenarios in which that expression could evaluate to true, depending on the types used and the context of the code.
In C, yes it can. If a is uninitialised then (even if there is no UB, as discussed here), its value is indeterminate, reading it gives indeterminate results, and comparing it to other numbers therefore also gives indeterminate results.
As a direct consequence, a could compare true with 1 in one moment, then compare true with 2 instead the next moment. It can't hold both those values simultaneously, but it doesn't matter, because its value is indeterminate.
In practice I'd be surprised to see the behaviour you describe, though, because there's no real reason for the actual storage to change in memory in the time between the two comparisons.
In C++, sort of. The above is still true there, but reading an indeterminate value is always an undefined operation in C++ so really all bets are off.
Optimisations are allowed to aggressively bastardise your code, and when you do undefined things this can quite easily result in all manner of chaos.
So I'd be less surprised to see this result in C++ than in C but, if I did, it would be an observation without purpose or meaning because a program with undefined behaviour should be entirely ignored anyway.
And, naturally, in both languages there are "tricks" you can do, like #define a (x++), though these do not seem to be in the spirit of your question.
The following program randomly prints seen: yes or seen: no, depending on whether at some point in the execution of the main thread (a == 0 && a == 1 && a == 2) evaluated to true.
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
_Atomic int a = 0;
_Atomic int relse = 0;
void *writer(void *arg)
{
++relse;
while (relse != 2);
for (int i = 100; i > 0; --i)
{
a = 0;
a = 1;
a = 2;
}
return NULL;
}
int main(void)
{
int seen = 0;
pthread_t pt;
if (pthread_create(&pt, NULL, writer, NULL)) exit(EXIT_FAILURE);
++relse;
while (relse != 2);
for (int i = 100; i > 0; --i)
seen |= (a == 0 && a == 1 && a == 2);
printf("seen: %s\n", seen ? "yes":"no");
pthread_join(pt, NULL);
return 0;
}
As far as I am aware, this does not contain undefined behavior at any point, and a is of an integer type, as required by the question.
Obviously this is a race condition, and so whether seen: yes or seen: no is printed depends on the platform the program is run on. On Linux, x86_64, gcc 8.2.1 both answers appear regularly. If it doesn't work, try increasing the loop counters.
I've been familiar with the ternary operator for quite some time now, and have worked with it in a few differnet languages. My understanding of the operator is this:
condition ? expr1 : expr2
However, in C++, the following code is legal:
int i = 45;
(i > 0) ? i-- : 1;
Aren't you, in effect, just writing 1; or i - 1;How is this a complete statement? I understand that the intention of the code is to decrement i if it's greater than 0, but I would've thought that the code would generate a compiler error as just being an expression, not a full statement. I expected code like this:
int i = 45;
i = (i > 0) ? i - 1 : i;
This is called expression statement. The expression is evaluated and its value is discarded.
Even this is valid:
42;
although it does nothing. Only side effects (like i--, assignment, etc) in the expression have effects.
In fact, many statements we use are expression statements: assignments, function calls, etc:
a = 42;
foo();
That is a valid expression. You might have received a warning because you are not saving the result of the expression, but that you have the i-- your statement does have an effect.
In C++, an expression like 1 is a perfectly valid statement with no side effects. You could very feasibly write this function:
void f() {
1;
}
In fact, even this is correct.
void f() {
;;;;
}
A literal statement evaluates its arguments but does nothing more. The system views 1; as being just like func();. The only difference is that while func(); would logically have some side effects, 1; does not so it ends up being a no-op. The ternary operator evaluates like an if-statement, so the second form is only evaluated if the operand is true. Thus:
(i > 0) ? i-- : 1;
If i is greater than 0, the second form is evaluated. When it is evaluated, it carries its side effect, which decrements i by 1. Otherwise, the third form is evaluated, which does nothing. Although this block of code works, it is not incredibly readable, so while it's nice toy code a real if-statement is ideal for situations like this. For the same reason, this line would have the same effect but be frowned upon for being equally unreadable.
((i > 0) && (i--)) || 1;
Assuming you didn't overwrite the boolean operators, this code will short-circuit and behave like the ternary operator. If i is not greater than 0, then the && need not evaluate its second operand since the && is false, but the || must since it might be true. Inversely, if i is greater than 0, the && needs to evaluate but the || already knows it's true.
Aren't you, in effect, just writing 1; or i - 1;
No: i-- is not the same as i - 1. In the first case, the value of i is modified. In the second case it is not.
In the event that i less than or equal to zero, then you're correct that the resulting 'code' will be 1. However, the compiler will realise that this is not a useful thing to execute and so it ought to generate code equivalent to:
if( i > 0 ) i--;
Some (including myself) would consider that using the ternary operator in this fashion is bad style. Just for fun, here's another way someone might write it that's also not very nice (also more likely to generate compiler warning):
i > 0 && i--;
In the end, style is a matter of preference. The compiler, for the most part, will decide the best way to turn your code into assembly. So you owe it to yourself to write code that is clear and concise.
I have the following code:
while( int()(uStartFrame - iFrameOffset) < 1)
{
iFrameOffset--;
}
uStartFrame and iFrameOffset are both unsigned long, so the < statement is a little difficult, I think.
However, I thought that I fixed it using int().
But the loop runs infinitively, so I guess it doesn't work.
Can somebody help?
Thank you!
while( uStartFrame < iFrameOffset + 1)
{
iFrameOffset--;
}
Or even better
if(uStartFrame < iFrameOffset + 1)
iFrameOffset = uStartFrame - 1;
The last line also shows the possible error. If uStartFrame is 0, then there's no unsigned long variable x that can fulfil uStartFrame == x + 1.
The cast is wrong, you should cast it like this,
(int)(uStartFrame - iFrameOffset) < 1
but this C-style cast is not really C++ style, in your case a static_cast is preferable:
static_cast<int>(uStartFrame - iFrameOffset) < 1
static_cast<unsigned long>(uStartFrame - iFrameOffset) < 1
Apart from that, when you write int()(x) you define a function that returns an integer and accepts no parameters, and then invoke it with uStartFrame - iFrameOffset as an argument. It shouldn't even compile, well at least gcc 4.8 rightfully complains about this.
Your compiler obviously does compile it and maybe even wrongly treats it as a function that returns an un-initialized integer, most likely 0, and that possible explains why your loop runs forever.
You're casting the test (uStartFrame-iFrameOffset) into int, not the iFrameOffset. So, if the iFrameOffset is big (max could be 2^64-1 - or bigger depending on system), then you might need 2^64 loops to get to the end.
This could be as much as a giga seconds. So, you should rethink this loop. It's not a goo idea.
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.
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
How to check for equals? (0 == i) or (i == 0)
Why does one often see “null != variable” instead of “variable != null” in C#?
Why do some experienced programmers write expressions this way?
What is the meaning of NULL != value in C++?
For example,
int k =5;
if( 5 == k )
{
}
is preferred over
if (k == 5)
{
}
Is it considered only for formatting purpose or is there any reason behind it?
Because that form makes it harder to introduce a bug by forgetting one of the equals signs. Imagine if you did this:
if (k = 5)
This was intended as a comparison, but it's now an assignment! What's worse, it is legal, and it will mess up your program in multiple ways (the value of k is changed, and the conditional always evaluates to true).
Contrast this with
if (5 = k)
This is not legal (you cannot assign to a literal) so the compiler will immediately flag it as an error.
That said, this style of writing code (assignments within conditionals) is not as prevalent today as it once was. Most modern compilers will flag this as a warning, so it's unlikely to go undetected. Personally I don't like the second form and since the compiler is there to help I don't use it.
If you mistype and write
if (k = 5) // instead of ==
then you likely just introduced a hard to find bug. (Actually, it used to be hard to find. Nowadays, most compilers will flag this as a warning.)
This, however, will result in a compile-time error
if (5 = k)
BTW, this style is called Yoda Conditions :-)
It's to avoid the mistake of
if( k = 5 ) {
}
which would always equal true.
A. Who said it's preferred ?!
the only reason i can think of it's to avoid:
int k =5;
if( 5 = k )//notice one "="
{
}
like this you will get a compilation error, while the other way will work. but I think it's less readable and less preferred.
First of all, most people prefer the second form, since it feels "more natural"; the first form is felt as "reversed", and in fact is often called "Yoda conditional".
The rationale behind using the first form is to avoid accidental assignment when typing = instead of == by error. Since in a conditional you can write any expression, = is allowed, so in case of mistyping the instruction
if(k = 5)
{
}
won't check if k is equal to 5, but will assign 5 to k and, since = returns a reference to its left hand operator, the condition will be evaluated as true and the if body will always be executed.
On the other hand, if you typed = instead of == in the Yoda conditional you would get
if(5 = k)
{
}
which results in a compilation error, since you can't assign anything to a literal (5).
Although they look like a good idea, "Yoda conditionals" are quite weird looking, and, most importantly, almost any good compiler with warnings turned on will warn you anyway if you write an assignment inside a conditional expression, so most people just use the "natural looking" form.
It's because a common typo is typing = instead of ==.