Search code examples
c++bitwise-operatorsternary-operatorlogical-operatorslogical-or

Bitwise and/or with ternary operator


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)


Solution

  • 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.