首页 文章

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

提问于
浏览
30

我需要编写表单的声明

a = a || expr;

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

当然,写上述内容的时间更短

a ||= expr;

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

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

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

  • 它使语法难以解析?

  • 处理这些案件的短路有一些微妙之处吗?

  • 它被认为是多余的(但这不是针对所有运营商分配的论据吗?)

EDIT

Please unlock this question because:

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

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

EDIT 2

现在看起来我原来的意图是错的 . 在 a = a || expr 语句中(其中 a 为整数且 expr 返回一个整数值,首先 aexpr 将隐式转换为"booleans",然后"boolean"值将分配给 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 回答

  • 3

    a ||= expr 由于其等效的 a = a || expr 的短路评估而存在问题 .

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

    “在声明a = a || expr ...中,首先将a和expr隐式转换为”booleans“,”

    这不太正确 . 如果 a 评估为 true ,则不会转换 expr . 如果 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();
    
  • 5

    我想简单的答案是 || 是一个布尔运算符:在C中,"boolean"是0或1.操作数被隐式转换为布尔值(我没有检查过's what the spec actually says, but it'是C的行为),结果是布尔值 .

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

  • 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; 的实施将非常简单,并且已经通过例如Lua中 .

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

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

    我希望我能帮助一点 .

  • 3

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

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

    您可以提出其他定义,例如: x ||= yif(!x) x = yx &&= yif(!y) x = y ,但这并不是很明显,并没有那么有用,所以没有包括在内 .

    1在C中它是bool .

相关问题