【问题标题】:Multidimensional array values getting modified even though passed by value [duplicate]即使按值传递,多维数组值也会被修改[重复]
【发布时间】:2019-10-21 03:46:03
【问题描述】:

我通常(按值)将二维数组传递给函数“elem”,该函数进一步将其传递给另一个函数“interchange”,该函数执行行交换操作并显示它。但问题是,在我从交换返回 main() 后,数组的值已更改为交换的结果数组,即使从技术上讲它们必须是三个不同函数(main、elem 和交换)的三个不同变量)。为什么会这样,我该怎么做才能使 main() 中的数组保持不变?

//include files... 

void interchange(float c[10][10],int m,int n)
{
    int i,j,p,q;
    float temp;

        printf("\nEnter the two row numbers to interchange:");
        scanf("%d%d",&p,&q);

        if((--p<m)&&(--q<n))
        {
            for(i=0;i<m;i++)
            {
                temp=c[p][i];
                c[p][i]=c[q][i];
                c[q][i]=temp;
            }
        } else
        {
            printf("Row numbers must be less than matrix order.\n");
            return;
        }

    printf("\nResultant matrix is:\n"); //print the array in interchange,c
    printf("\n");
    for(i=0;i<m;i++)
        {for(j=0;j<n;j++)
            {
                printf("%f\t",c[i][j]); 
            }
         printf("\n");
        }
}

void elem(float b[10][10],int m,int n)
{
    int ch;
    do
    {
        printf("\n1:Row interchange\t 2:Exit elementary transformations\n\nEnter the choice:");
        scanf("%d",&ch);  //get user input to decide which operation to perform (there are more operations in actual code)

        switch(ch)
        {
            case 1: interchange(b,m,n);
                    break;

            case 2: printf("\nExiting elementary transformations.\n");
                    break;
        }

    }while(ch!=2);
}

int main()
{
    float a[10][10];
    int m,n,i,j;
    printf("Enter the order of the matrix:");
    scanf("%d%d",&m,&n);
    printf("Enter the matrix elements:");
    for(i=0;i<m;i++)
    {
        for(j=0;j<n;j++)
        {
            scanf("%f",&a[i][j]);
        }
    }

        //print the entered array a
    printf("\n");
    for(i=0;i<m;i++)
        {for(j=0;j<n;j++)
            {
                printf("%f\t",a[i][j]); 
            }
         printf("\n");
        }

    elem(a,m,n);

        //print the original array in main()   
        printf("\n");
    for(i=0;i<m;i++)
        {for(j=0;j<n;j++)
            {
                printf("%f\t",a[i][j]); 
            }
         printf("\n");
        }
}

这是我得到的输出:

Enter the order of the matrix:2 2
Enter the matrix elements:1 2 3 4

1.000000        2.000000
3.000000        4.000000

1:Row interchange        2:Exit elementary transformations

Enter the choice:1

Enter the two row numbers to interchange:1 2

Resultant matrix is:

3.000000        4.000000
1.000000        2.000000

1:Row interchange        2:Exit elementary transformations

Enter the choice:2

Exiting elementary transformations.

3.000000        4.000000
1.000000        2.000000

对不起,破旧的代码,我从一个更大的文件中抢救出来。

【问题讨论】:

  • 在 C 中,所有数组都作为某种指针传递——因此被调用函数可以修改调用函数中的数组(除非函数中的声明中有 const 限定符以防止此类修改)。数组不会批量复制。
  • 仅供参考,表达式中数组 id 的“值”(例如函数的参数)是第一个元素的基地址。考虑一下。如果你想真正按值传递一个数组,把它埋在一个结构中。
  • 数组表达式“衰减”为指针表达式,除非它们是 sizeof 或一元 &amp; 运算符的操作数 - 当您将 a 传递给 elem 时,它会隐式转换为计算参数列表时指向第一个元素 (&amp;a[0]) 的指针 (int (*a)[10]),因此所有 elem 接收到的都是指针值。无法将数组表达式作为参数传递并在被调用函数中将其解释为数组。
  • if 条件if((--p&lt;m)&amp;&amp;(--q&lt;n)) 中存在错误。 qn 的列数进行比较(递减后),而不是与m 的行数进行比较。此外,由于您正在检查pq 的范围,因此您也应该检查负值。
  • @Ian Abbot 确实!直到现在我只用方阵执行程序,所以我从来没有注意到这个错误。感谢您指出!

标签: c multidimensional-array pass-by-reference


【解决方案1】:

为什么会这样?

是的,您正在“按值”传递它,但您必须了解这在 C 中的含义。当您将数组传递给函数时,它会衰减到指针。然后该指针按值传递,但该值是数组中第一个元素的地址。

我该怎么做才能使 main() 中的数组保持不变?

一些不同的东西,取决于你想要什么。您可以在函数中创建一个临时数组,然后复制所有值。将开头替换为:

void interchange(const float arr[10][10],int m,int n) {
    float c[10][10];
    for(int i=0; i<10; i++)
        for(int j=0; j<10; j++)
            c[i][j]=arr[i][j];

只要没有其他错误,您的代码就会按照您想要的方式运行。添加const 的效果是,如果您尝试将arr 中的元素分配给某物,则会出现编译器错误。

【讨论】:

  • 不应该是float c[10][10];吗?另一种选择是使用一维数组char row[10]来存储矩阵行索引,而不是复制整个矩阵。
  • @IanAbbott 你完全正确。修好了。
  • 谢谢。我明天会尝试这个并更新结果,虽然我不能使用 const 因为在我的主程序中,数组需要被操作很多次。不过我会尝试添加临时数组。
【解决方案2】:

对于函数参数,您不能“按值”传递数组。

当编译器看到参数声明 float c[10][10] 时,会将其翻译为 float (*c)[10]

所以传递的是一个指针(指向数组的第一个元素)。您修改指针指向的内存,这会反映在调用函数中。

【讨论】:

  • 谢谢。这些事情非常令人困惑!
猜你喜欢
  • 2015-03-15
  • 2018-01-15
  • 1970-01-01
  • 1970-01-01
  • 2021-08-05
  • 2016-04-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多