Are several inline undefined comparison variables behavior?

I told my friend (who is studying C) that he could not compare several variables at the same time:

int main(){ int a[4]; scanf("%d %d %d %d", &a[0], &a[1], &a[2], &a[3]); if(a[0] < a[1] < a[2] < a[3]){ printf("OK!\n"); } else{ printf("I've told ya\n"); } } 

So, to prove that I am right, I encoded the program above, and then executed it with 1 2 3 4 . Surprisingly, printed OK! . And therefore, I did not know what to tell him, because I was sure that it was not so.

Finally, is this or not undefined behavior?

+6
source share
7 answers

No, it is clearly defined. It just differs from semantics in what you expect.

The expression is evaluated as follows:

 if (((a[0] < a[1]) < a[2]) < a[3]) { 

Each comparison gives a boolean result ( 0 or 1 ).

The result (boolean) of a[0] < a[1] compared with a[2] , and the (logical) result of this comparison is compared with a[3] .

I'm sure there are some legitimate use cases, but they are rare at best.

The right way to express what you are trying to express is

 if (a[0] < a[1] && a[1] < a[2] && a[2] < a[3]) { 
+12
source

This is not undefined behavior, it just does not do what you think. It is equivalent

 (((a[0] < a[1]) < a[2]) < a[3]) 

1 for true, 0 for false. Therefore, if a [0] is less than a [1], then it compares [2] with 1, otherwise, with zero. Etc.

+4
source

This is not undefined behavior, this is unexpected behavior.

In C and C ++, you cannot do math-like comparisons. You can compare two things at the same time. So, if you want a < b < c < d , you should write:

 if (a < b && b < c && c < d) ... 
+4
source

Since you added C ++ to the mix, you could just do

 if ( std::is_sorted(a, a+4) ) puts("OK!"); 
+3
source

Behavior is defined, but does not do what you expect, so do not.

Your expression will look like this:

 ((a[0] < a[1]) < a[2]) < a[3] 

where each x <y turns into 1 or 0, which means that it is ALWAYS true if a [3] is greater than 1 and possibly true if a [3] is greater than 0.

+2
source

This is not undefined behavior, but it does not do what it thinks it does. <associative from left to right, so first a[0] < a[1] computed, which leads to true . Then true < a[2] is evaluated (equivalent to 1 < a[2] ), which results in true . Etc. You got the correct match result. For example, β€œ2 1 0 1” will also give the truth. Use

 a[0] < a[1] && a[1] < a[2] && a[2] < a[3] 

or, in general, if your array is long:

 for(i=1,ok=1;i<n&&ok;i++)ok &= a[i-1] < a[i]; 
+2
source

The order of evaluation <operator, when it looks like this, is clearly defined. The code you wrote is equivalent to:

 bool x; x = a[0] < a[1]; if(x == true) { x = true < a[2]; } else { x = false < a[2]; } if(x == true) { x = true < a[3]; } else { x = false < a[3]; } if(x == true) { printf("OK!\n"); } else { printf("I've told ya\n"); } 

true always evaluates to the integer 1, false to 0. As you can tell, this code makes no sense.

+1
source

All Articles