This was a question in my preparation exam:
int val = 0;
int x = 0;
int y = 1;
if (x < val < y)
printf(" true ");
else
printf(" false ");
Why is this true? I tried changing x and val and it ignored those changes, as long as y was larger than 0 (so 1, 2, 3...) the statement was true. So for example: if (3 < 9 < 2) will be true.
( 2 < 9 < 3 ) is evaluated as ( ( 2 < 9 ) < 3).
In the first step 2 < 9 is evaluated to be true, which is represented as integer value 1 and results in ((1) < 3) for the second step.
That is obviously true.
You probably wanted something like ((x < val) && ( val < y)).
The first is check whether x < value. If true, it return 1 so the next is check whether 1 < y.
First you check x and val. If its value is correct, you convert it to 1 and check it with y.
If you build with -Wall option using GCC compiler you will get a warning like this:
<source>:7:11: warning: comparisons like 'X<=Y<=Z' do not have their mathematical meaning [-Wparentheses]
if (x < val < y)
Detailed explanation of this warning can be found in GCC documentation. The relevant part is as following:
-Wparentheses
...
Also warn if a comparison like x<=y<=z appears; this is equivalent to (x<=y ? 1 : 0) <= z, which is a different interpretation from that of ordinary mathematical notation.
...
NOTE: Comparisons in C follow the left to the right approach. (if all operators are of same priority)
Thus, evaluation of (2 < 9 < 3) will be done in 2 steps:
step 1. evaluation of (2 < 9): it is true, thus, integer value=1.
step 2. evaluation of ( (2 < 9) < 3 ) i.e (1 < 3): it is also
true.
I think you wanted (2 < 9) && (9 < 3).
In C, usually operators follow left to the right approch(except operators like =, -=, +=, etc.). Operator <, > follows left to the right approch too. So, 2<9<3 in C means (2 < 9) < 3. 2 < 9 is 1, so, the value of 2 < 9 < 3 is 1.
You can fix it with (2 < 9) && (9 < 3).
Related
This question already has answers here:
Chaining multiple greater than/less than operators
(6 answers)
Closed 9 months ago.
I would like to know how i is evaluated in this code in C language ?
int x = 10, y = 20, z = 5, i;
i = x < y < z;
printf("%d\n",i);
The result of a relational operator is either integer 1 if the condition is true or 0 otherwise. And relational operators evaluates from left to right.
So this statement
i = x < y < z;
is equivalent to
i = ( x < y ) < z;
and as x is less than y then it can be also rewritten like
i = 1 < z;
that initialize the variable i by 1 because 1 is less than 5.
From the C Standard (6.5.8 Relational operators)
6 Each of the operators < (less than), > (greater than), <= (less than
or equal to), and >= (greater than or equal to) shall yield 1 if the
specified relation is true and 0 if it is false.107) The result has
type int.
If you will rewrite the statement like
i = x < y && y < z;
then the result of the expression will be equal to 0 because y is not less than z.
in C, is
if((d[i] != 1) && (d[i] != 2))
same as
if(d[i] != (1 | 2))
and why is
if(d[i] != (1 || 2))
rejected by the compiler?
is there a way to simplify the first statement, if I want to check for many constants? which to say check whether d[i] is 1,2,3,4,5. So I would reject it if d[i] is e.g. 6.
1) No. 1 | 2 is 3 (you can test this by printing it out) so if(d[i] != (1 | 2)) does the same thing as if(d[i] != 3)
2) It shouldn't be. 1 || 2 should be 1, so if(d[i] != (1 || 2)) should do the same thing as if(d[i] != 1). If you get an error for this, then I suspect that's because you're using your compiler's "treat warnings as errors" option (-Werror for gcc or clang).
No, They are not same. if((d[i] != 1) && (d[i] != 2)) cannot be further simplified.
Lets come to other codes. if(d[i] != (1 | 2)) it first performs (1|2), which results in 3. and then performs comparison if(d[i] != 3), you certainly don't want that, right?
Now In if(d[i] != (1 || 2)) , first operation done is (1 || 2) it results in true (type is boolean) and your statement effectively becomes if(d[i] != true) //comparing int to boolean, due to type mismatch compiler warns against it.
If you want to check for multiple numbers, use a for loop and array as
int constants[]= {1,2,3,4,5}; //constants to check against
int ar_size = sizeof(constants) / sizeof(constants[0]); //ar_size will adjust to array size, you can use vector for simplification
bool inArray = false; //default is false.
for (int it_i = 0; i < ar_size; it_i++)
{
if (constants[it_i] == d[i]) //Checking is done here
inArray = true;
}
//just use inArray to find if element was in constants[] or not
if (inArray)
{
//code
}
To check a variable against multiple values, the variable must be specified each time as in a == 1 || a == 2 || ... or a != 1 && a != 2 && ....
Specifying only constants as in a != (1 || 2 ||..) will not give the expected result, because 1 || 2 is expanded to 1 (Refer to Short circuit evaluation). Compiler may give warning because it looks like an unlikely (unintended) construct.
Condition 1.
if((d[i] != 1) && (d[i] != 2))
This will check both condition d[i] !=1 and d[i]!=2 that is if d[i] not equal to 1 and 2 condition will run.
If first condition fails it will not check d[i] != 2.
Condition 2.
if(d[i] != (1 | 2))
here (1 | 2) will return 3.
1==> 0001
2==> 0010
------
Bitwise OR= 0011 ==> result will be 3
means it will check d[i] !=3
Condition 3.
if(d[i] != (1 || 2))
1||2 will return TRUE so it will give you error.
as d[i] is having integer value and you are trying to compare it with Boolean value which cause error.
d[i] is integral value, and result of (1 || 2) is boolean true. Comparison of boolean and integral value in if(d[i] != (1 || 2)) makes no sense to compiler.
In a 8-bit number, 1 is represented as:
0000 0001
2 is represented as
0000 0010
The bitwise OR of those two numbers results in
0000 0011
which is 3.
Hence,
d[i] != (1 | 2) is the same as d[i] != 3. That is, obviously, very different from (d[i] != 1) && (d[i] != 2).
if(d[i] != (1 || 2))
should not be rejected by the compiler. That statement is equivalent to:
if(d[i] != 1)
Updated answer
is there a way to simplify the first statement, if I want to check for
many constants? which to say check whether d[i] is 1,2,3,4,5. So I
would reject it if d[i] is e.g. 6.
Absolutely:
if ((d[i] >= 1) && (d[i] <= 5))
See, it's really not that complicated. The compiler can likely optimize the heck out of this.
For what it's worth, detecting x in [1..5] is actually a very difficult expression to optimize with bitmask logic. If you write out a Karnaugh Map for the lower three bits of the integer range, nothing helpful shows up. The best I could simplify it to is this:
if (4 >= (unsigned)(d[i]-1))
I compiled some code in Visual Studio to see how it would optimize (x >= 1) && (x <= 5) in a retail build. It optimizes exactly like the expression above. That is: ((x-1) < 4)
In C if((d[i] != 1) && (d[i] != 2)) implies that this condition is true if and only if d[i] is neither equal to 1 nor d[i] is equal to 2(Both conditions have to be satisfied simultaneously).
which is not same as if(d[i] != (1 | 2)) as this implies that this condition is true if and only if d[i] is not equal to bitwise OR of 1 and 2 which is 0001|0010=0011 (3).So indirectly it is checking if d[i] is not equal to 3.
if(d[i] != (1 || 2)) is not rejected by compiler try gcc <filename.c> and execute the a.out file. This will check d[i] with exclusive OR of 1 and 2 which is 1.So indirectly this condition evaluates to if d[i] is not equal to 1.
Coming to your final question your condition can be easily evaluated by this check:
if((d[i]>=1) && (d[i]<=5)) where 1 is the initial value and 5 is the final value of your check.
Assume we have an expression like
(x > 5)
in C language. Is there any guarantee given by the language / standard that the expression will be evaluated to 0 when it's false and to 1 when it's true?
Yes, it is guaranteed by the standard.
As per the C11 standard document, chapter 6.5.8, paragraph 6, [Relational operators]
Each of the operators < (less than), > (greater than), <= (less than or equal to), and >=
(greater than or equal to) shall yield 1 if the specified relation is true and 0 if it is
false. The result has type int.
Update: Same chapter and paragraph for C99 standard also.
In gcc, it will be evaluated as one and zero.
Consider following program
#include <stdio.h>
int main(void)
{
int a = 3;
int b = 4;
if((a > b) == 0)
printf("a > b is false\n");
if((a < b) == 1)
printf("a < b is true\n");
return 0;
}
It gives output
a > b is false
a < b is true
I would like to do this in one line (C programming language):
int x = index >> 8;
int y = x < 10 ? x+1 : x+2;
Is it possible? How do I reference to value before ? sign, if I don't have it stored in separate integer?
"int y = (index >> 8) < 10 ? [what]+1 : [what]+2;"
You simply need to repeat the expression:
int y = (index >> 8) < 10 ? (index >> 8) + 1 : (index >> 8) + 2;
It's not very nice, or readable, so I don't get why you must do it this way. There's no built-in way in the language to reference the expression before the ?. Since expressions can have side-effects in C, it would be quite hairy if there was.
The way you have this expression is the best you can get there without code repetition.
If you absolutely need it to be a single string, you can simply do the following:
int y = (index >> 8) < 10 ? (index >> 8)+1 : (index >> 8)+2;
Because C makes no distinction between whitespace characters, you can have it in a single line:
int x = index >> 8; int y = x < 10 ? x+1 : x+2;
...which is completely valid C.
However your y and x values are not inter-dependent, so you can simplify the expression to just y:
int y = index >> 8; y = y < 10 ? y+1 : y+2;
If your y already exists, you can make use of the little-used comma operator to eliminate the semi-colon and reduce it to a single statement:
y = ( y = index >> 8 ), y < 10 ? y+1 : y+2;
Note that you cannot use the comma operator inside a value declaration statement because in that context it becomes the sequence separator.
It is generally not useful to try to optimize source code in this way. C does not specify what specific operations the computer must perform; C specifies what results a program must achieve. (By means of the “as if” model in C. The program the compiler produces must produce results as if you stepped through the specific operations you wrote, but those results can actually be obtained by any sequence of instructions the implementation chooses. The program only needs to reproduce results, not mechanisms.)
Generally, you should write your code to be clear, and you should allow the optimizer in the compiler to do its job of performing the calculations efficiently.
It is possible using this form :
int y = (y = index >> 8) < 10 ? y+1 : y+2;
Here, y get assigned the temporary value of index >> 8, so you can reuse that value after the ? operator.
And contrary to David's similar answer, this form work inside a value declaration statement as well.
Alternatively, by removing the ternary. The shift being equivalent to a division by 256, we can compare the value also before the shifting.
int y = (index >> 8) + 1 + (index >= 2560);
Of course, index should be positive for this to work.
EDIT: the expression has also the advantage of having no temporary write access and no sequence point.
For the following code snippet I get the output as 1. I want to know how it came?
void main()
{
int x=10,y=20,z=5,i;
i=x<y<z;
printf("%d",i);
}
i=x<y<z;, gets interpreted as i=(x<y)<z, which in turn gets interpreted as i=1<z, which evaluates to 1.
10 is less than 20, resulting in 1, and 1 is less than 5, resulting in 1. C doesn't chain relational operators as some other languages do.
It operates as follows:
Since < is a logical expression, x<y i.e 10<20 is true i.e 1. So it becomes 1<z i.e 1<5 which is again true i.e. 1 which is assigned to i. So i is 1.
This is because your code evaluates as:
void main()
{
int x=10,y=20,z=5,i;
i=((x<y)<z); //(x<y) = true = 1, (1 < 5) = true
printf("%d",i);
}
what output did you want?
In C,
i = 2 < 3; //i == 1.
i = 4 < 3; //i == 0.
If condition evaluates to false, value returned is 0, and 1 otherwise.
Also, x < y < z will be evaluated as ((x < y) < z).
x<y // 1 as (10 < 20) will return 1
result of(x<y)<z // 1 as (1<5) will return 1
C++ doesn't support multi-part comparisons like that.
x < y < z
is interpreted as
(x < y) < z
or that is, determine if x < y, then see if that boolean is less than z.
There's some discussion on why that is over at the software engineering StackExchange.
When you find yourself trying to do this, instead you need to write it as two separate comparisons joined by a boolean:
(x < y) && (y < z)