&& =和|| =运算符

可能重复:
为什么Java没有条件和条件运算符的复合赋值版本? (&& =,|| =)
为什么“&& =”运算符不存在?

今天在工作中我写了以下LOC(b和b1的真实身份是保密:)

b &&= b1; // meaning b = b && b1; 

我盯着它看了几秒钟,发现没有这样的操作员。 只是为了确定,我点击了编译,但失败了。 为了确定我已经咨询了标准。

是否存在没有此类运营商的具体原因? 我能想到一些:

  1. 由于&&的短路评估, b &&= b1b = b && b1可能不等效。
  2. && =很难看
  3. 很少需要&& =

我并不认为拥有这样的运营商是非常有用的,不。 我也没有声称上述三个原因中的任何一个或全部都不足以避免创建该运营商。 我的问题如下:我可能有更严重的理由要监督吗?

我不知道为什么这个问题和一些答案都提到相应逻辑运算符的短路行为是一个潜在的问题。

定义&&=||=运算符绝对没有与短路相关的问题。 它们应该用+=和其他类似的运算符统一定义,这意味着a &&= b应该等于a = a && b ,但是在&&= version中只评估一次。 这意味着,如果a最初为零,则根本不评估b 。 简单。

因此,他们在语言中不存在的唯一原因是,“仅仅因为”。

我之前也想要它们。 我怀疑丑陋本身就是决定因素,短路行为是迄今为止我听到的最好的反对他们的论据。

另一个影响因素是C被设计为靠近金属运行,几乎所有运算符都直接对应于主要架构中的指令。 我认为x86,PPC等没有直接实现b &&= b1;的指令b &&= b1;

运营商不存在的最大原因可能是K&R没有想到任何有吸引力的定义方式。 我有时也想要一个 – > =运算符(ptr – > = next将等同于ptr = ptr-> whatever)。

我认为使用&& =的一个问题是,以下哪个最有用,或者它应该是什么并不明显:

   if(lhs && rhs)lhs = 1; 别的lhs = 0;
   if(!rhs)lhs = 0; 别的lhs =!(!lhs));
   if(lhs &&!rhs)lhs = 0;
   if(!rhs)lhs = 0;

第一个变体是语法最明确的建议,但从实际角度来看,如果两个术语都不为零,那么单独留下左侧比将其设置为“1”通常更有用。

顺便说一句,我经常希望逗号运算符的变体可以评估左侧,保存值,然后评估右侧,并返回左侧的值。 相当于:

 int foo(int p1,int p2)返回p1;

除了适用于任何类型(p2不需要与p1类型相同,并且可能无效),并且具有保证的从左到右的评估顺序。 对于像非单位步骤的后增量索引这样的事情会非常方便,例如,arr [ptr~,ptr + = 2]; 或者对于某些类型的数据交换操作,例如,var1 =(var2~,var2 = var1); 等等

因为a && b的结果总是01 ,我认为对C99 _Bool类型的解释只是明确的。 由于在创建C时不存在,因此不包括该运算符。 而现在没有人轻易地向C添加另一个运算符,因为这会对所有现有解析器产生影响。

就个人而言,我会投票给你的第一个理由。 布尔运算符具有短路语义,如果转换为对齐运算符,这将导致一些非常粗糙的情况。 要么你不再使它们短路,要么你创造了一些奇怪的“可选”赋值运算符(只做左边的东西,只有当LHS上的值已经非零时才分配结果)。 无论哪种方式,你都会产生微妙的错误,因为人们会期待其他行为。

编辑:错误的语言,但仍然适用

我同意你的三个原因,虽然有一种情况我在编写自定义反序列化例程时感叹缺少这个运算符。 在一些不正确的序列化对象不是真正“exception”的情况下(并且为了防止非常常见的C#中的exception开销),我会使用布尔返回值来表示反序列化操作是否成功。

这段代码完全是理论上的,Nested1,Nested2和Nested3都是结构体:

 public struct ComplexStruct { private Nested1 nested1; private Nested2 nested2; private Nested3[] nested3; public bool Read(Reader reader) { bool ret = true; int nested3Length = 0; ret &&= nested1.Read(reader); ret &&= nested2.Read(reader); ret &&= reader.ReadInt32(ref nested3Length); for(int i = 0; (ret && i < nested3Length); i++) { ret &&= nested3[i].Read(reader); } return ret; } }