本文没有针对任何人、任何文章的意思,只是自我反省的一篇博文,提醒自己以后多多思考问题、深入问题。
早上刚刚看到这篇博文“面试奇葩——交换两变量值的一些邪门歪道(http://www.cnblogs.com/pmer/p/3373843.html)”。
才发现自己的思考越来越少了,背诵越来越多了
以前只是想,交换两个标量有这么多的方法,背下来,以后面试用。哈。装B一下。。
可是却没有深入思考程序的可用性、以及实用性。更深层次的去理解内部的东东。。
模仿garbageMan同志的思路走下去。。(个人也思考了一下这些问题)
int i = 111, j = 222;
1.值类型变量交换----借助第三个变量(这个估计通用,没啥说的)
#region 值类型变量交换----借助第三个变量
Console.WriteLine("i:" + i + ",j:" + j);
int temp = 0;
temp = i;
i = j;
j = temp;
Console.WriteLine("i:" + i + ",j:" + j);
#endregion
2.值类型变量交换----加法(这个有点意思),深入了一下
直接考虑极值
i = int.MaxValue; //最大值啊
j = int.MaxValue - 1;
Console.WriteLine("i:" + i + ",j:" + j);
//i=2147483647,,,,j=2147483646 //开始时候的值
i = i + j; //加法啊
Console.WriteLine("i:" + i + ",j:" + j);
//估计这时候后 就是学名的溢出,但是,计算的时候估计是把符号位一起计算上了,,使得最高位符号位由0变1 ,i结果也就变成了-3
//i=-3 ,,,,,j=2147483646
j = i - j;
i = i - j;
//这两步是交换计算
Console.WriteLine("i:" + i + ",j:" + j);
//i=2147483646,,,,j=2147483647
//估计内部计算,会把这个最高位的符号位,一起参与计算了。结果使得结果正确。。
语法课本说这是“溢出”,,但实际确是,没有编译报错,执行没有报错,,估计直接把符号位,拉进了计算。。
应该是cpu计算的时候没有什么符号位,只不过是程序语言底层把有符号数的第一位翻译成符号位,在cpu内部直接就是高地位的计算。个人理解,(不太了解具体内部,,希望大牛详解)
3.值类型变量交换----乘除法,直接pass啦
#region 值类型变量交换----乘除法,直接pass啦 j=0 编译器会直接报错,估计是对“/”除法有着最基本的校验重写
//i = i * j;
//j = i / j;
//i = i / j;
#endregion
4.值类型变量交换----整形 异或运算,相异出1
#region 值类型变量交换----整形 异或运算,相异出1
i = int.MaxValue; j = int.MaxValue - 1;
Console.WriteLine("i:" + i + ",j:" + j);//i=2147483647,j=2147483646
i = i ^ j;
Console.WriteLine("i:" + i + ",j:" + j);//i=1,j=2147483646
j = j ^ i;
Console.WriteLine("i:" + i + ",j:" + j);//i=1,j=2147483647
i = i^j;
Console.WriteLine("i:" + i + ",j:" + j);//i=2147483646,j=2147483647
#endregion
这个确实,只是用与整数运算,浮点类型等类型不适用。。
5.对于上文笔者提到的异或潜在问题(同一个数交换数值),有点不敢苟同
#include <stdio.h>
#include <limits.h>
void swap( int * p , int * q )
{
* p = * p ^* q ; //这里取相同地址的值,是同一个数值 ,10(上一次交换的) ,两个相同的数值异或结果为0,这时候赋值给*p,而*p、*q有指向同一地址,所以p、q都是0
* q = * q^* p ; //这里两者都是0
* p = * p^* q ; //这里两者都是0
}
int _tmain(int argc, _TCHAR* argv[])
{
int i = 5 , j = 10 ;
puts("交换前:");
printf("i = %d , j = %d " , i , j );
swap( & i , & j);
puts("交换后:");
printf("i = %d , j = %d " , i , j );
//自己和自己交换
puts("交换前:");
printf("i = %d " , i );
swap( & i , & i);
puts("交换后:");
printf("i = %d " , i );
return 0;
}
同一个数异或本身就是0,这是后你又使用指针,指向同一个地址,所以都是指向0的地址,以后再怎么异或都是0和0异或了,所以就是0,保险的话你写在程序里,就没有问题了
本文没有针对任何人、任何文章的意思,只是自我反省的一篇博文,提醒自己以后多多思考问题、深入问题。透过现象看待问题的本质。。。