为啥 C/C++ 中没有 ^^ 运算符?
Posted
技术标签:
【中文标题】为啥 C/C++ 中没有 ^^ 运算符?【英文标题】:Why is there no ^^ operator in C/C++?为什么 C/C++ 中没有 ^^ 运算符? 【发布时间】:2010-10-24 15:34:19 【问题描述】:&
有 &&
。 |
有 ||
。为什么^
没有^^
?
我知道它不会短路,但它会有不同的语义。在 C 中,true
实际上是任何非零值。按位异或并不总是与逻辑异或相同:
int a=strcmp(str1,str2);// evaluates to 1, which is "true"
int b=strcmp(str1,str3);// evaluates to 2, which is also "true"
int c=a ^^ b; // this would be false, since true ^ true = false
int d=a ^ b; //oops, this is true again, it is 3 (^ is bitwise)
既然您不能总是依赖1
或-1
这样的真值,那么^^
运算符不是很有帮助吗?我经常不得不做这样奇怪的事情:
if(!!a ^ !!b) // looks strange
【问题讨论】:
因为它看起来太幸福了。 ^_^ C++ 是关于痛苦的!优化!优化! (免责声明:这是一个笑话。不要当真。) 我很感兴趣但很困惑……逻辑异或 a^^b 要求在 a 中设置的所有位都在 b 中未设置,在 b 中设置的所有位在 a 中都未设置?跨度> 这不是一个反问句。难道原c/c++语言的创造者不需要回复才能真正回答这个问题吗? @Terry:我想这有点夸张,因为 C 不会突然添加 ^^ 运算符,但我对此很好奇,我正在设计一种编程语言。我想知道我是否应该包括它。现在,其中有一个 ^^ 运算符,但如果有人给出一个很好的理由反对它,我会删除它。 @Zifre:我编辑了你的问题,让人们更清楚为什么你可能想要这样做。如果您不喜欢我的更改,请随时恢复。我会在评论中提出建议,但 cmets 中没有格式。希望这会有所帮助。 【参考方案1】:Dennis Ritchie answers
没有
^^
运算符的原因既有历史原因,也有实际原因。实际情况是:操作符没有太多用处。
&&
和||
的主要目的是利用它们的短路评估,不仅是出于效率原因,而且更多的是为了表达性和正确性。 [...] 相比之下,^^
运算符将始终强制计算表达式的两个分支,因此没有效率提升。此外,确实需要^^
的情况非常罕见,尽管可以创建示例。当您堆叠操作员时,这些情况会变得越来越少和陌生--if (cond1() ^^ cond2() ^^ cond3() ^^ ...) ...
当奇数个
condx()
s 为真时,执行结果。相比之下,&&
和||
类似物仍然相当合理和有用。
【讨论】:
哇,我没想到 Dennis Rithchie 会回答我的问题 :)。见特里多纳吉的评论。他确实给出了一些非常好的观点。 +1【参考方案2】:从技术上讲,已经存在一个:
a != b
因为如果操作数的真值不同,这将评估为真。
编辑:
Volte的评论:
(!a) != (!b)
是正确的,因为我上面的答案不适用于 int
类型。如果他添加他的答案,我将删除我的。
再次编辑:
也许我忘记了 C++ 中的一些东西,但我越想这个,我就越想知道你为什么会写if (1 ^ 2)
。 ^
的目的是对两个数字进行异或运算(计算结果为另一个数字),而不是将它们转换为布尔值并比较它们的真值。
对于语言设计者来说,这似乎是一个奇怪的假设。
【讨论】:
对于非布尔输入,您需要使用((!!a) != (!!b))
(带有额外的括号表示偏执!)。
当然,这仅适用于布尔类型,因此您需要强制转换才能将其与 OP 示例中的整数一起使用。无论如何 +1。
'(!a) != (!b)' 会产生同样的效果。
我实际上读错了这个问题,我在他的代码中看到了 cmets(它说的是真假)但错过了 int 类型 - 尽管我的 C++ 是我必须相信你们的铸造有点生锈
不,1 != 2 为真,而 1 ^^ 2 为假。你最终不得不将它包裹在 !s 中,在这种情况下,我认为 !!1 ^ !!2 会更清楚。【参考方案3】:
对于非bool
操作数,我想您希望a ^^ b
被评估为:
(a != 0) ^ (b != 0)
好吧,您有上述选项,并且您在其他答案中列出了一些选项。
运算符 ^^
对于 bool
操作数来说是多余的。只讨论布尔操作数,为了争论,让我们假设^
是仅按位的,而^^
作为逻辑异或存在。然后您有以下选择:
&
- 按位与 - 始终计算两个操作数
&&
- 逻辑与 - 并不总是评估两个操作数
|
- 按位或 - 总是计算两个操作数
||
- 逻辑或 - 并不总是评估两个操作数
^
- 按位异或 - 必须始终评估两个操作数
^^
- 逻辑异或 - 必须始终评估两个操作数
他们为什么不创建^^
将数值转换为bool
s,然后充当^
?这是个好问题。也许是因为它比&&
和||
更容易混淆,也许是因为您可以使用其他运算符轻松构造^^
的等价物。
【讨论】:
他的观点是,如果你要进行操作 (1 ^^ 2),当他认为它应该像 (1 ^^ 2) 一样评估为 true 时,它会评估为 false。我并不是说我同意,我只是指出这实际上并不是多余的。【参考方案4】:我无法说出 Kernighan 和 Ritchie 发明 C 时的想法,但您简要提到了“不会短路”,我猜这就是原因:它不是可以始终如一地实施它。你不能像 AND 和 OR 那样短路 XOR,所以 ^^ 不能完全并行 && 和 ||。所以作者很可能已经决定,进行一种看起来与其他操作相似但并不完全相似的操作会比根本没有操作更糟糕。
就个人而言,我使用 && 和 || 的主要原因用于短路而不是非按位。其实我很少使用位运算符。
【讨论】:
实际上,Ritchie 几乎是自己创造了 C。 Kernighan 与人共同撰写了经典的 C 书籍 The C Programming Language,但并未参与创建该语言。【参考方案5】:上面发布的另一种解决方法(即使它需要代码中的另一个分支)是:
if ( (a? !b : b ) )
相当于异或。
【讨论】:
是的,当然它们是变通方法,但我认为真正的 ^^ 运算符会更清楚您的意图。你的例子不是那么明显。【参考方案6】:在 Java 中,^
运算符在用于两个布尔操作数时确实会执行逻辑 XOR(就像 Java 中的 &
和 |
在应用于布尔值时分别执行非短路逻辑 AND 和 OR )。与 C/C++ 的主要区别在于 C/C++ 允许您混合整数和布尔值,而 Java 不允许。
但我认为无论如何将整数用作布尔值是不好的做法。如果你想做逻辑运算,你应该坚持使用bool
值,或者0 或1 的整数。然后^
可以很好地作为逻辑XOR。
一个类似的问题是,你将如何在 C/C++ 中进行非短路逻辑 AND 和 OR?通常的答案是分别使用&
和|
运算符。但同样,这取决于 bool
或 0 或 1 的值。如果您允许任何整数值,那么这也不起作用。
【讨论】:
【参考方案7】:不管^^
作为运营商的情况如何,你以strcmp()
为例很糟糕。它不返回真值(真或假),它返回其输入之间的关系,编码为整数。
当然,任何整数都可以在 C 中解释为真值,在这种情况下,0 为“假”,所有其他值为“真”,但这与 strcmp()
返回的相反。
你的例子应该开始了:
int a = strcmp(str1, str2) == 0; // evaluates to 0, which is "false"
int b = strcmp(str1, str3) == 0; // evaluates to 0, which is also "false"
您必须将返回值与 0 进行比较,以将其转换为正确的布尔值,指示字符串是否相等。
使用“正确的”布尔值,典型地表示为 0 或 1,按位 ^
运算符也能更好地工作......
【讨论】:
以上是关于为啥 C/C++ 中没有 ^^ 运算符?的主要内容,如果未能解决你的问题,请参考以下文章
C语言中已经有了malloc和free,为啥还需要new和delete?
为啥 % 运算符不能用于 C/C++ 中的浮点数但可以用于 Java 和 C#? [复制]