C 无效交换(int*a,int*b)不使用数组

C 无效交换(int*a,int*b)不使用数组,c,arrays,pointers,swap,C,Arrays,Pointers,Swap,C编程新手,尝试创建交换两个变量值的void函数。当我希望交换两个整型变量的值时,下面的函数可以很好地用于a=11,b=33的函数调用交换(&a,&b): 但是,当我尝试对数组的两个元素执行此操作时,它不能正确地用于交换(&a[0]、&a[2])。但是,它与以下功能一起工作: void swap(int i, int j, int a[]) { int h = a[i]; a[i] = a[j]; a[j] = h; } *a += *b; *b = *a - *b; *a -=

C编程新手,尝试创建交换两个变量值的void函数。当我希望交换两个整型变量的值时,下面的函数可以很好地用于a=11,b=33的函数调用交换(&a,&b):

但是,当我尝试对数组的两个元素执行此操作时,它不能正确地用于交换(&a[0]、&a[2])。但是,它与以下功能一起工作:

void swap(int i, int j, int a[]) {
  int h = a[i];
  a[i] = a[j];
  a[j] = h;
}
*a += *b;
*b = *a - *b;
*a -= *b;
有人知道为什么第一个是单变量,而不是数组元素吗?当然有一个很好的解释,我在这里错过了。欢迎所有帮助,提前谢谢

以下是完整的程序:

#include <stdio.h>
#include <stdlib.h>


void swap(int *a, int *b) {
  *a += *b;
  *b = *a - *b;
  *a -= *b; 
}

void selectionSort(int a[], int len) {
  int i, j, min;
  for (i = 0; i < len; i++) {
    min = i;
    for (j = i+1; j < len; j++) {
      if (a[j] < a[min]) {
        min = j;
      }
    }
    swap(&a[i], &a[min]);
  }  
}

int main(int argc, char * argv[]) {
  int a[5] = {5, 4, 3, 2, 1};
  int len = 5, i;

  selectionSort(a, len);


  for (i = 0; i < len; i++) {
    printf("%d ", a[i]);
  }
  printf("\n");

    return 0;
}
#包括
#包括
无效交换(int*a,int*b){
*a+=*b;
*b=*a-*b;
*a-=*b;
}
无效选择排序(整数a[],整数长度){
int i,j,min;
对于(i=0;i

数组值的输出为1 2 0 0。

如果是数组元素,只需使用[0]和[2],而不使用“&”运算符,因为数组本身就是指针,所以您不需要提供任何引用。

让我猜一下——所有值都变为零

如果
a==b
,则交换函数将中断。尝试:

void swap(int *a, int *b) {
  if (a != b)
  {
      *a += *b;
      *b = *a - *b;
      *a -= *b; 
  }
}

最好编写经典的交换函数

void swap( int *a, int *b )
{
   int tmp = *a;
   *a = *b;
   *b = tmp;;
}
或更改功能选择按以下方式排序

   void selectionSort(int a[], int len) {
      int i, j, min;
      for (i = 0; i < len; i++) {
        min = i;
        for (j = i+1; j < len; j++) {
          if (a[j] < a[min]) {
            min = j;
          }
        }
        if ( min != i ) swap(&a[i], &a[min]);
      }  
    }
void selectionSort(int a[],int len){
int i,j,min;
对于(i=0;i
当两个参数都指向同一个对象时,
swap
函数将失败。我发现您是这样做的,在调用
swap
之前添加了
printf
调用,您可以自己尝试:

printf("swap(%d, %d)\n", i, min);
swap(&a[i], &a[min]);
交换
函数中使用的算法:

void swap(int i, int j, int a[]) {
  int h = a[i];
  a[i] = a[j];
  a[j] = h;
}
*a += *b;
*b = *a - *b;
*a -= *b;
似乎是为了避免创建临时变量,但代价是(a)两个对象相同时失败,以及(b)如果出现算术溢出,则可能出现未定义的行为。2的补码整数上的算术运算通常具有概括语义,这(我认为)会给出正确的结果,但这是一个不必要的复杂性。如果处理浮点运算,它会有更多的问题,因为算术运算可能会溢出或丢失精度。还有一个类似的按位异或攻击,它有着大部分相同的问题(而这在浮点运算中根本不起作用)。声明临时文件将解决以下两个问题:

const int old_a = *a;
*a = *b;
*b = old_a;
(通常将临时文件命名为
tmp
,但我想给它一个更明确的名称,告诉您它的用途;添加
const
告诉读者,在初始化它之后,它不会被更改。)

但这不是唯一的问题。您试图与其自身交换数组元素这一事实表明,
selectionSort
函数也存在缺陷;正确的排序算法永远不会将元素与自身交换,因为这样做是无用的


如果您修复了
选择排序
,您可能不需要修复
交换
,但我还是建议您这样做。

“它无法正常工作”是对问题的糟糕描述。这可能是一个情境问题。如果出于某种原因,您的调用代码对自身执行元素交换(交换(&a[1],&a[1]);),这将取消选中。。。我对该方法的初步理解是,它会无意中将值设置为0。可能发生了这种情况?请注意,有一种更好的方法(操作更少,不会因溢出而出现未定义的行为)可以在不增加空间的情况下交换两个变量:
*a^=*b*b^=*a*a^=*ba==b
时,code>仍然不起作用。我推荐下面@DavidSchwartz的答案。要自行解决此类问题,建议添加printf和/或使用调试器:-)数组衰减为指针,但
[]
包含一个偏差。是的,这一个可行!很好,非常感谢。为什么如果两个元素相等,则交换并置为0?@jake1992:When
*a==*b
(两个元素相等)它工作正常。您的问题是当
a==b
时,即两者都指向同一个元素。非常感谢您的解释,了解了有关指针的一些新知识!修复
swap
功能是不够的。他将一个元素与其自身交换的事实表明排序例程中存在一个bug。