Bitwise and/or with ternary operator
Asked Answered
V

3

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)

Veronica answered 17/8, 2015 at 14:22 Comment(8)
@YuHao These are all just for fun. I know readability is very very important. :)Veronica
C++ Operator PrecedenceRaddle
: nothing doesn't make sense. you need a value for the ternary operator.Eleanor
What does this question have to do with operator precedence?Baucis
@CoryKramer I saw that page. and I was not able to get any good clue to answer this question.Veronica
@KarolyHorvath right. Then former code should not be compiled. But it works! :-oVeronica
@Baucis good point. please suggest any other title. I think precedence may not give any help now.Veronica
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.Glarum
B
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.

Babysitter answered 17/8, 2015 at 14:48 Comment(0)
A
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

Anticathexis answered 17/8, 2015 at 14:38 Comment(0)
B
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.

Babysitter answered 17/8, 2015 at 14:48 Comment(0)
R
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.

Risarise answered 17/8, 2015 at 14:57 Comment(1)
Wow. This is gcc extension. #10143625 thank you!Veronica

© 2022 - 2024 — McMap. All rights reserved.