按位与/或运算符与三元运算符的使用方式是什么?

5

看这个小片段。

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

(y 是最小值,v 是当前比较的值。这样做可以让您更容易地思考。)

这段代码的含义很简单。
如果当前值 v 小于最小值 y,则设置新的最小值 (y=v)。但排除了 v=0 的情况。

然后我想,如果生成“逆向代码”,结果应该是相同的。我的意思是,

y>v&v?y=v:;

这段代码应该做同样的事情。但是它不能被编译。错误如下。

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

很奇怪,我认为两个代码是相同的。如果后面的三元运算符有误,前面的也应该有同样的问题。但实际上并没有。

有人能解释一下为什么吗?

下一个问题。我插入了一个0来编译。y>v&v?y=v:0;
然后我得到了一个错误的答案。 所以我把&改成了&&y>v&&v?y=v:0;
最终我得到了正确的答案。但是没有这些过程,使用|运算符就可以完成所有操作。为什么?

<additional info>

我的编译器版本如下。

$ 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

编译选项:

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

如果您需要一个样本代码来测试,这将有所帮助。
#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. 欢迎纠正我的英语错误)

我们可以使用版本控制工具来管理IT项目的源代码。最流行的版本控制系统是Git,它是一个免费开源的工具,可以跟踪代码修改并记录每次更改的细节。GitHub是一个基于Git的Web平台,用户可以在上面托管他们的代码,并与其他人协作。团队成员可以通过克隆仓库、拉取更新和提交变更等方式进行代码共享和合作。Git和GitHub是IT开发过程中必备的工具,对于单个开发者和团队都非常重要。


@YuHao 这些只是为了好玩。我知道可读性非常非常重要。 :) - plhn
C++ 运算符优先级 - Cory Kramer
“: nothing” 没有意义。你需要为三元运算符提供一个值。 - Karoly Horvath
@Barry 很好的观点。请提出其他的标题建议。我认为优先级现在可能没有任何帮助。 - plhn
1
使用 -std=c++11 -Wall -Wextra -pedantic 编译,你会得到 warning: ISO C++ does not allow ?: with omitted middle operand [-Wpedantic] 和一些其他有关运算符优先级的有用警告。同样地,使用 Clang 编译,会得到更多有用的警告。 - bogdan
显示剩余3条评论
3个回答

4

这些代码并不会执行相同的操作,因为它们的条件并不是彼此的否定。试试用 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


2
在这个片段中:
y<v|!v?:y=v;

v的值被转换为bool并用!取反。由于按位或|的两侧都是布尔值,因此|的行为类似于逻辑或。

在另一种情况下:

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

在这里,没有转换为 bool,相反,y>v 的结果会被转换为 int。按位与 & 的结果因 v 的最低位而异。它的行为不像逻辑与。
这应该像原始版本一样工作:

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

因为有一个转换为布尔值的过程。


2
条件运算符的语法如下:
逻辑表达式 ? 真值表达式 : 假值表达式
第一个例子中,
y<v|!v ? : y=v;

您缺少true-expression。使用-Wall编译时,我在g++编译器中收到以下警告。

socc.cc: In functionint 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;

在第二个例子中,
y>v&v ? y=v : ;

您缺少false-expression。由于某种原因,g++将其视为错误而不是警告。

您可以通过为它们提供虚拟值来修复它们。

顺便说一下,您正在使用按位运算符|&。我确定这是一个小错误。

您可以使用:

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

或者

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

更新

表达式

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

这不是合法的C/C++语法,但它被g++作为扩展支持。更多信息可以在C条件运算符('?')与空第二参数中查看。


1
哇,这是gcc扩展。https://dev59.com/KWkw5IYBdhLWcg3wGGq8 谢谢! - plhn

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接