5

Look at this tiny snippet.

y<v|!v?:y=v;

(y is minimum value, and v is current compared value. This way would make you think easier.)

This snippet’s meaning is simple.
If current value v is smaller then minimum value y, set new minimum value(y=v). But v=0 case is excluded.

Then I thought if the 'adverse code' could be generated, the result should be same. I mean,

y>v&v?y=v:;

This code should do same thing. But it cannot be compiled. The error is as follows.

error: expected expression
  for(int v: a) v=abs(a[i]-v), x>v?:x=v, y>v&v?y=v:;
                                                   ^

It’s weird. I think two codes are same each other. If latter ternary operator is erroneous, former should have same problem. But it didn’t.

Can someone explain why?

Next question. I inserted a 0 to compile. y>v&v?y=v:0;
Then I got a false answer. So I changed & to &&. y>v&&v?y=v:0;
Finally I got a right answer. But without these process, using | operator can do all. Why?

<additional info>

My compiler version is as follows.

$ gcc --version
Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
Apple LLVM version 6.1.0 (clang-602.0.53) (based on LLVM 3.6.0svn)
Target: x86_64-apple-darwin14.4.0
Thread model: posix

And compile option:

g++ -std=c++11 my.cpp

If you want to have a sample code to test, this would help.

#include <iostream>
#include <vector>
using namespace std;
int working(int i, vector<int> a) {
  int y=INT_MAX;
  for(int v: a) v=abs(a[i]-v), y<v|!v?:y=v;
  return y;
}

int not_working(int i, vector<int> a) {
  int y=INT_MAX;
  for(int v: a) v=abs(a[i]-v), y>v&v?y=v:0;
  return y;
}

int main() {
  vector<int> b({-5,-2,2,7});
  cout << working(2, b) << endl;
  cout << not_working(2,b) << endl;
  return 0;
}

(p.s. correction of my poor english is always welcomed)

plhn
  • 5,017
  • 4
  • 47
  • 47
  • @YuHao These are all just for fun. I know readability is very very important. :) – plhn Aug 17 '15 at 14:29
  • [C++ Operator Precedence](http://en.cppreference.com/w/cpp/language/operator_precedence) – Cory Kramer Aug 17 '15 at 14:37
  • `: nothing` doesn't make sense. you need a value for the ternary operator. – Karoly Horvath Aug 17 '15 at 14:38
  • What does this question have to do with operator precedence? – Barry Aug 17 '15 at 14:46
  • @CoryKramer I saw that page. and I was not able to get any good clue to answer this question. – plhn Aug 17 '15 at 14:50
  • @KarolyHorvath right. Then former code should not be compiled. But it works! :-o – plhn Aug 17 '15 at 14:51
  • @Barry good point. please suggest any other title. I think precedence may not give any help now. – plhn Aug 17 '15 at 14:51
  • 1
    Compile with `-std=c++11 -Wall -Wextra -pedantic` and you'll get `warning: ISO C++ does not allow ?: with omitted middle operand [-Wpedantic]` and a few other helpful warnings related to operator precedence. Similarly from Clang, with even more helpful warnings. – bogdan Aug 17 '15 at 14:55

3 Answers3

4

The codes do not do the same thing, because the conditions are not the negation of each other. Try it with y == 3, v == 2:

y < v | !v => 3 < 2 | !2 => false | !true => false | false => 0 | 0 => 0

y > v & v => 3 > 2 & 2 => true & 2 => 1 & 2 => 0

Angew is no longer proud of SO
  • 167,307
  • 17
  • 350
  • 455
2

In this snippet:

y<v|!v?:y=v;

the value of v is converted to a bool and negated with !. Because both sides of the bitwise or | are bools, | behaves like the logical or.

In the other case:

y>v&v?y=v:0;

there is no conversion to bool, and instead the result of y>v is converted to int. The bitwise and & gives varying results, depending on the lowest bit of v. It does not behave like the logical and.
This should work like the original:

y>v&!!v?y=v:0;

because there is a conversion to bool.

alain
  • 11,939
  • 2
  • 31
  • 51
2

The syntax of the conditional operator is:

logical-expression ? true-expression : false-expression

In the first one,

y<v|!v ? : y=v;

you are missing true-expression. I get the following compiler warning with g++ when compiled with -Wall.

socc.cc: In function ‘int main()’:
socc.cc:14:12: warning: the omitted middle operand in ?: will always be ‘true’, suggest explicit middle operand [-Wparentheses]
    y<v||!v?:y=v;

In the second one,

y>v&v ? y=v : ;

You are missing false-expression. For some reason, g++ treats this as an error instead of a warning.

You could fix that by providing a dummy value for both of them.

By the way, you are using bitwise operators | and &. I am sure that is a small error.

You can use:

(y<v || !v) ?  0 : y=v;

or

(y>v && v) ? y=v : 0;

Update

The expression

(y<v || !v) ? : y=v;

is not legal C/C++. It is supported by g++ as an extension. More can be seen at C conditional operator ('?') with empty second parameter.

Community
  • 1
  • 1
R Sahu
  • 204,454
  • 14
  • 159
  • 270
  • 1
    Wow. This is gcc extension. http://stackoverflow.com/questions/10143125/c-conditional-operator-with-empty-second-parameter thank you! – plhn Aug 17 '15 at 15:08