【问题标题】:Swapping 2 arrays in C在 C 中交换 2 个数组
【发布时间】:2018-04-10 10:34:07
【问题描述】:

我需要在一个函数中交换 2 个数组的值。问题是我可以改变主要的任何东西,只是函数本身。它应该接收 2 个整数数组,并交换它们。问题是,我不知道数组的大小,而且据我所知,它们甚至可以有不同的大小。试试这段代码:

    int main()
{
    int size = 4;  //Please notice that I'm using this only to print the array
    int a[] = {1,2,3,4};
    int b[] = {5,6,7,8};
    printArr(a,"a",size);
    printArr(b,"b",size);
    swapArray(a,b);
    printf("Swapped:\n");
    printArr(a,"a",size);
    printArr(b,"b",size);
}

还有这个功能:

 void swapArray(int **a,int **b)
{
    int *p = *a;
    *a = *b;
    *b = p;
}

而 printArr 只是打印数组:

void printArr(int arr[],char name[],int size)
{
    printf("%s:\t",name);
    for(int i=0;i<size;i++){
        printf("%d\t",arr[i]);
    }
    printf("\n");
}

我得到了一个非常奇怪的结果:

a:   1    2    3   4
b:   5    6    7   8
Swapped:
a:   5    6    3   4
b:   1    2    7   8

我想了解它发生的原因,而不仅仅是一个可行的解决方案。 谢谢你:)

【问题讨论】:

  • 如果你启用编译器警告,那么你会从编译器那里得到一些关于你做错了什么的非常有用的信息,特别是关于你对swapArray的调用(我很惊讶甚至编译)。
  • 您确定您阅读的作业正确吗?像这样交换硬连线数组甚至没有意义,尽管交换指针(可以用作指向数组的指针)确实如此。

标签: c arrays pointers swap


【解决方案1】:

在本次通话中

swapArray(a,b);

参数表达式的类型为int *,而函数参数的类型为int **。没有从 int * 类型到 int ** 类型的隐式转换。所以编译器会发出诊断信息。

在任何情况下,实现的交换功能都没有意义。你的程序有未定义的行为,至少因为它试图交换指针而不是数组本身。

考虑到数组不是指针,尽管在极少数例外的表达式中,它们确实被隐式转换为指向其第一个元素的指针。

要交换两个数组的元素,您必须分别交换每对元素。 你必须提供数组中元素的数量。否则数组需要有一个标记值。

这是一个演示程序,展示了如何定义函数 swap。

#include <stdio.h>

void printArr( const int a[], size_t n, const char *s )
{
    printf( "%s:\t", s );

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

void swapArray( int *a, int *b, size_t n )
{
    for ( size_t i = 0; i < n; i++ )
    {
        int tmp = a[i];
        a[i] = b[i];
        b[i] = tmp;
    }
}

int main(void) 
{
    enum { N = 4 };
    int a[N] = { 1, 2, 3, 4 };
    int b[N] = { 5, 6, 7, 8 };

    printArr( a, N, "a" );
    printArr( b, N, "b" );
    putchar( '\n' );

    swapArray( a, b, N );


    printArr( a, N, "a" );
    printArr( b, N, "b" );
    putchar( '\n' );

    return 0;
}

它的输出是

a:  1 2 3 4 
b:  5 6 7 8 

a:  5 6 7 8 
b:  1 2 3 4 

您可以使用指针交换原始数组的视觉表示。但在这种情况下,数组本身不会被交换。

考虑以下程序。

#include <stdio.h>

void printArr( const int a[], size_t n, const char *s )
{
    printf( "%s:\t", s );

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

void swapArray( int **a, int **b )
{
    int *tmp = *a;
    *a = *b;
    *b = tmp;
}

int main(void) 
{
    enum { N = 4 };
    int a[N] = { 1, 2, 3, 4 };
    int b[N] = { 5, 6, 7, 8 };

    printArr( a, N, "a" );
    printArr( b, N, "b" );
    putchar( '\n' );

    int *pa = a;
    int *pb = b;

    swapArray( &pa, &pb );

    printArr( pa, N, "pa" );
    printArr( pb, N, "pb" );
    putchar( '\n' );

    printArr( a, N, "a" );
    printArr( b, N, "b" );
    putchar( '\n' );

    return 0;
}

它的输出是

a:  1 2 3 4 
b:  5 6 7 8 

pa: 5 6 7 8 
pb: 1 2 3 4 

a:  1 2 3 4 
b:  5 6 7 8 

如您所见,数组没有交换。然而,指向数组第一个元素的指针被交换了。使用指针可以模拟数组的交换。

相对于 C C++ 有一个模板函数std::swap 用于数组,确实可以像这样简单地调用

std::swap( a, b );

【讨论】:

    【解决方案2】:

    我猜在你的平台上指针的大小是 64 位的,而 in 的大小是 32 位的。

    调用swapArray 时,编译器会隐式地将int 的数组重新解释为指针数组。 (这些是指向int 的指针,但这在这里无关紧要)。 swapArray 然后只是交换这些指针数组的第一个元素。

    幸运的是,您原来的 int 数组足够大,因此不会发生非法访问。

    由于指针是 64 位,因此对应两个 int,它们被交换。

    【讨论】:

    • 这解释了很多!非常感谢
    【解决方案3】:

    在 C 中,数组不是可以交换的单一“事物”。您需要逐个元素地交换它。

    您可以一次性交换这些数组“事物”的唯一情况是它们是指向数组的指针。

    int *a = malloc(n*sizeof(int));
    int *b = malloc(n*sizeof(int));
    int *tmp;
    tmp=a; a=b; b=tmp;
    

    【讨论】:

    • 非常感谢。不幸的是,我不能使用 malloc。分配从一开始就是不正确的,但至少我在这个过程中学到了很多东西。
    猜你喜欢
    • 2016-04-24
    • 1970-01-01
    • 2012-01-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-06
    • 2011-04-20
    相关资源
    最近更新 更多