总结了一下大致常见的关于交换两数值的问题。
先附上第一段代码
void swap2(int a,int b)
{
int tmp;
tmp = a;
a = b;
b = tmp;
}
这段代码的问题不用多说,定义了变量a,b,交换仅仅限在此函数中交换,当从此函数出去,a,b生命周期就结束,所以不能调用此函数来完成数值的交换。
第二段
void swap3(int *p1,int *p2)
{
int *tmp ;
tmp = p1;
p1 = p2;
p2 = tmp;
}
这段代码,引入指针变量进行数值交换,但是在进行交换操作的时候,没对指针变量进行解引用,所以交换的仅仅是两个指针变量所保存的地址,数值并没有进行交换。另一个问题就是,就算此处进行了解引用,这里定义的*tmp也是野指针,又称悬挂指针,会非法访问地址,所以错误。
第三段
void swap1(int *p1,int *p2)
{
int tmp;
tmp = *p1;
*p1 = *p2;
*p2 = tmp;
}
这段代码定义了指针变量,定义中间变量tmp,随即对指针变量进行解引用通过中间变量对数值进行交换。
综上三段代码的比较,总结如下:
1.指针可以突破不在同一函数的界限
2.一定要记得解引用
下边分析一下不使用第三变量对数值进行交换
void swap(int *p1,int *p2)
{
*p1 = *p1 + *p2;
*p2 = *p1 - *p2;
*p1 = *p1 - *p2;
}
经过普通测试,这种方法,还不错,很聪明,没有bug显示,接下来对这段代码进行其他测试分析bug
void swaplen(int *arr,int len)//调用
{
for(int i = 0,j = len -1; i <= j;++i,--j)
{
swap(&arr[i],&arr[j]);
}
}
void show(int *arr,int len)//打印
{
for(int i = 0;i <= len-1;++i)
{
printf("%3d",arr[i]);
}
}
这里两段代码第一个是调用上述不使用第三变量进行数值交换的方式来对一个数组内的数字进行逆置交换,第二段是将交换后的数组数字进行打印查看结果
进行如下测试时,结果正确:6 5 4 3 2 1
int arr[] = {1,2,3,4,5,6};
swaplen(arr,sizeof(arr)/sizeof(arr[0]));
show(arr,sizeof(arr)/sizeof(arr[0]));
进一步更换测试
将数组内数字增加一个7,数组长度变为七,arr[] = {1,2,3,4,5,6,7},结果错误:
7 6 5 0 3 2 1
经调试发现,当进行交换第四个数字4时,两个指针解引用均为数字4,做和求差,直接篡改数值,将数字4变为0。
所以这种方法并不好,他隐含了bug,对奇数个数字交换时,中间数值会被更改。