如何使用 XOR 赋值运算符 ^= 来反转 c 中的数组

Posted

技术标签:

【中文标题】如何使用 XOR 赋值运算符 ^= 来反转 c 中的数组【英文标题】:How XOR Assignment operator ^= is utilized to reverse an array in c 【发布时间】:2021-10-29 13:32:51 【问题描述】:

我遇到过这个函数

void reverseArray(int *a,int n)

for(int i=0,j=n-1;i<j;i++,j--)

a[i]^=a[j]^=a[i]^=a[j];


它正在反转给定的数组,但我无法理解这如何反转数组,Xor 运算符不是只返回非公共位。 那么反转给定数组的逻辑是什么。

【问题讨论】:

Re“非公共位”:当你翻转a[j]中的非公共位时,它使这些位具有它们在a[i]中的值,因此结果等于@987654327 @。然后,从右到左,a[i]^=a[j] 找到非公共位 (^) 并将它们 (^=) 存储在 a[i] 中。然后a[j]^=a[i]^a[j] 翻转a[j] 中的那些位,使其等于原始a[i]。然后a[i]^=a[j]^=a[i]^=a[j] 将存储在a[i] 中的非公共位与a[i](现在在a[j] 中)的原始值进行异或,这样翻转非公共位以生成原始a[j],这存储在a[i] 需要注意的是,这条语句的行为并没有被C标准定义,因为a[i]的更新是没有顺序的。 请注意,有两种截然相反的方法可以回答这个问题。 (1) 这段代码的作者试图实现一个(反常的)目标,我们可以解释这个目标是什么,以及它是如何实现的。但是(2)正如您自己亲眼所见,此代码在第一次阅读时是不可能理解的。此外,它是未定义的:它甚至不能保证工作。因此,虽然这可能是一个值得学习的有用示例,但绝对绝对不是值得钦佩、模仿或用于真实、实用的程序的东西! 在C FAQ list 中查看Question 20.15c。 见What is the difference between two different swapping function? 【参考方案1】:

a ^= b ^= a ^= b; 是一种交换两个数字的奇特方式,称为XOR swap。

您应该更喜欢可读性更高的std::swap,或(在 C 中)临时变量。

【讨论】:

s/fancy/obfuscated/. C++ 有std::reverse。你甚至不需要在 for 循环中使用 std::swap【参考方案2】:

表达式a^=b^=a^=b 的目的是交换ab 的值。如果我们将其拆分(其中a_0b_0ab 的原始值)会变得更加清晰:

    第一次分配,a^=b 使a_1=(a_0^b_0)。 第二次分配,b^=a 使b_1=(b_0^a_1)=(b_0^(a_0^b_0))=a_0 第三次分配,a^=b 使a_2=(a_1^b_1)=((a_0^b_0)^a_0)=b_0

因此,我们最终得到 a 的原始值为 b,反之亦然。

虽然表达式a^=b^=a^=b 可能有效,但它实际上是未定义的行为,因为C 标准没有指定赋值的顺序。相反,它必须明确排序:a^=b; b^=a; a^=b;

【讨论】:

以上是关于如何使用 XOR 赋值运算符 ^= 来反转 c 中的数组的主要内容,如果未能解决你的问题,请参考以下文章

C++赋值运算符,我们可以用copy来代替吗?

Go+赋值运算

C语言中同等级运算的先后顺序

求 高手 C语言 数组和数组之间能直接赋值吗

在 C 中评估赋值运算符的左操作数有啥意义?

复合赋值运算符