一个奇怪的经济掉期






2.52/5 (6投票s)
一种使用 XOR 运算符交换任何类型两个变量的方法。
引言
这篇文章包含代码,用于回答以下问题:如何在不使用中间变量的情况下,交换两个 int
类型变量的值?
开始思考
交换整数类型变量的一个简单算法是
/** Changes the value between two integer variables. In other words, in the end of
the function the first variable will have the second variable value and vice-versa.
*/
void normalSwap(int &first, int& second)
{
int third = first;
first = second;
second = third; // first variable value into second one
}
int main()
{
int first = 13;
int second = 42;
cout << "first: " << first << ", second: " << second << endl;
normalSwap(first, second);
cout << "first: " << first << ", second: " << second << endl;
}
输出
first: 13, second: 42
first: 42, second: 13
其中一种解决方案(至少我知道一种)是使用 XOR 运算符。这个二进制运算符具有一个不太简单的特性,即能够在单个存储空间内保存两个位模式。如果你有一个或两个模式,你将得到第二个模式。让我们回顾一下真值表
void xorTable()
{
cout << "XOR Table\\n---------\\n"
<< "0 XOR 0 = " << ( 0 ^ 0 ) << '\\n'
<< "1 XOR 0 = " << ( 1 ^ 0 ) << '\\n'
<< "0 XOR 1 = " << ( 0 ^ 1 ) << '\\n'
<< "1 XOR 1 = " << ( 1 ^ 1 ) << '\\n';
}
输出
XOR Table
———
0 XOR 0 = 0
1 XOR 0 = 1
0 XOR 1 = 1
1 XOR 1 = 0
换句话说,假设我们有值 1 和 0。使用 XOR 保存两者,我们得到 1,因为
1 (first pattern) XOR 0 (second pattern) = 1 (patterns together)
稍后,我们可以使用第二个模式获得第一个模式
1 (patterns together) XOR 0 (second pattern) = 1 (first pattern)
为了获得第二个模式,我们只需要使用第一个模式
1 (patterns together) XOR 1 (first pattern) = 0 (second pattern)
使用相同的逻辑应用于所有可能的组合,你将看到我们可以始终使用其中一个模式获得两个模式。由于逻辑与位无关,因为位运算符一次处理一位,我们可以将该技术扩展到组合两个整数、两个字符串,甚至“存储在一串 1 和 0 中的两个事物”。
template<typename>
void universalXor(const T& first, const T& second, T& result)
{
typedef unsigned char byte;
const byte* pFirst = reinterpret_cast<const>( &first );
const byte* pSecond = reinterpret_cast<const>( &second );
byte* pResult = reinterpret_cast<byte*>( &result );
for( size_t i = 0; i < sizeof(first) && i < sizeof(second); ++i )
pResult[i] = pFirst[i] ^ pSecond[i];
}
这是最基本的对称密钥算法。第一个模式扮演明文的角色,第二个模式扮演密码的角色,第三个模式将是混淆后的文本。为了查看明文,我们需要密码。
Using the Code
代码很简单。代码只需要像普通的交换一样调用函数即可。
int main()
{
// swaping ints
int x = 13, y = 42;
cout << "x: " << x << ", y: " << y << '\\n';
universalXor(x, y, x);
universalXor(x, y, y);
universalXor(x, y, x);
cout << "x: " << x << ", y: " << y << "\\n\\n";
// swaping strings
char str1[50] = "xor test", str2[50] = "we accept strings!";
cout << "str1: " << str1 << ", str2: " << str2 << '\\n';
universalXor(str1, str2, str1);
universalXor(str1, str2, str2);
universalXor(str1, str2, str1);
cout << "str1: " << str1 << ", str2: " << str2 << '\\n';
return 0;
}
输出
x: 13, y: 42
x: 42, y: 13str1: xor test, str2: we accept strings!
str1: we accept strings!, str2: xor test
关注点
我认为值得说明的是,这只是一种有趣的编码技巧,而不是专业的生产代码。换句话说,这是一段用于学习某些概念并使用这些概念来创建更有用的东西的代码。