为什么C没有逻辑赋值运算符?

时间:2010-08-17 09:26:46

标签: c logical-operators

我需要编写表单

的语句
a = a || expr;

应评估expr,并将结果分配给a iff a未设置。这取决于逻辑OR的短路能力。

写上述内容的较短方式当然是

a ||= expr;

但是(令我惊讶的是)C没有逻辑赋值运算符。

所以我的问题是双重的。首先,是否有更短的方法来编写标准C中的第一个语句(三元运算符更糟糕 - a = a ? a : expr要求我拼出a三次)。

其次,为什么C中没有逻辑分配?我能想到的可能原因是:

  • 它会使语法难以解析吗?
  • 处理这些案件的短路有一些微妙之处吗?
  • 它被认为是多余的(但不是针对所有运营商分配的论据?)

编辑

请解锁此问题,因为:

  • 与之相关的问题(作为所谓的副本)尚未得到答复。该问题的(已接受)答案表明||=不存在,因为重复了|=的功能。这是错误的答案。 |=不会短路。

  • C和C ++不是同一种语言。我想知道为什么C没有它。实际上,像C ++这样的衍生语言,特别是Java(没有像Edmund的答案中提到的遗留代码问题那样)这个问题使得这个问题更加有趣。

编辑2

现在看起来我原来的意图是错误的。在a = a || expr语句中(其中a是整数而expr返回一个整数值,首先aexpr将隐式转换为“布尔值”,然后将“布尔”值赋给a。这将是不正确的 - 积分值将丢失。谢谢,Jens和Edmund。

因此,对于问题的第一部分,正确的方法,而不是替代:),编码我的意图将是:

if (!a) a = expr;

a = a ? a : expr;

他们应该优化相同(我认为)虽然我个人更喜欢第一个(因为它少了一个a来打字。)

然而,问题的第二部分仍然存在。 Jens和Edmund关于a ||= expr中含糊不清的论点同样适用于a = a || expr。任务案例可以简单地视为正常案例:

  • a转换为布尔值
  • 如果为true,则整个表达式的值等于a的布尔值
  • 否则评估expr,将结果转换为布尔值,分配给a,然后将其返回

上述步骤对于作业和正常情况似乎都是相同的。

4 个答案:

答案 0 :(得分:5)

由于对等效a ||= expr的短路评估,

a = a || expr存在问题。

a ||= expr函数如a = a || expr考虑OP的断言:

  

"在陈述a = a || expr ...中,首先将a和expr隐式转换为"布尔","

这不太正确。如果expr评估为a,则不会转换true。如果expr类似于scanf()rand()或某些影响程序状态的函数,这会有所不同。

a ||= scanf("%d", &i) != 1;之类的代码只会尝试在a中使用false值扫描数据。虽然可以通过这种方式扩展语言,但是当前||&&集合的其他短路运算符可能会导致编码问题,而不是简单的简化。

另一方面:一种快速的,如果模糊的方式来编写代码,其中函数在出错时返回非零代码。

// Perform functions until an error occurs.
bool error = foo1();
error &&= foo2();  // Only valid if C was extended with &&=
error &&= foo3();

答案 1 :(得分:3)

我想简单的答案是||是一个布尔运算符:在C中,“boolean”是0或1.操作数被隐式转换为布尔值(我没有检查过那是什么规范实际上说,但它是C的行为方式),结果是布尔值。

改变语义以支持这种模式可能是可行的 - 直到有人依赖||做它总是做的事情。

答案 2 :(得分:3)

我找不到任何特殊原因,为什么运营商不存在(在C99中)。

所以我能找到的唯一原因是,C89中没有布尔类型,那些布尔运算符只能在if中使用。

示例:

int i = 5;

/* This should not make any difference,
   since or'ing with false, shouldn't change
   the value... dib di dib diddy...*/
i ||= 0; /* Actually: i = i || 0, which gives 'true' */

i现在为'1',对于大多数人来说这非常直观。

如果没有布尔类型,这个运算符显然不会带来任何清晰度或编码改进,这会使得另一个运算符出现。或者

在我看来,a ||= b;作为if(!a) a = b;的实施将非常简单,并且已经通过例如{{1}}实施。 LUA。

所以你的问题似乎有点儿,为什么C的设计方式与它的设计方式相同。 如果这个问题是关于C ++的话,你可以问Bjarne Stroustrup然后问他,进入他的是什么。既然事实并非如此,那么在我看来这似乎是一种死路,因为标准已经写了很久以前你不能再问人了,为什么h ***。

另一方面,这个不完整的算子集应该(在我看来)整数使用与你的相似的符号,因为在我看来,没有理由反对它。

我希望我能帮一点点。

答案 3 :(得分:2)

因为运算符||&&的返回类型与其左参数的类型不同。

||&&的返回类型始终为int 1 ,而左参数可以是任何整数,浮点或指针类型。操作数也不必是同一类型。因此,将x ||= y定义为x = x || y和将x &&= y定义为x = x && y,与其他扩充分配一致,将无法将结果存储在大多数类型的参数中。

您可以提出其他定义,例如: x ||= yif(!x) x = yx &&= yif(!y) x = y,但这并不是非常明显, 有用,因此不包括在内

1 在C ++中它是bool