如果已经分配了内存,那么在函数内部的数组中所做的更改是否会保留在主函数或调用函数中?

If memory is already allocated, will changes made in the array inside a function be preserved in the main or calling functions?

提问人:Pranav Vasishta 提问时间:3/6/2023 最后编辑:Pranav Vasishta 更新时间:3/7/2023 访问量:118

问:

在这个函数定义中,我采用了 2D 数组地址的参数。

void dynamic(int ***a,int r,int c)
{
    *a = (int**)malloc(sizeof(int*)*r);
    for(int i=0;i<r;i++)
    {
        (*a)[i] = (int*)malloc(sizeof(int)*c);
    }

}

我正在传递如下所示的参数,

dynamic(&a,r1,c1);

如果我直接将 2d 数组作为参数,那么它就不会接受输入。

但是,在这段代码中,在 add 函数中,我没有获取 2D 数组的地址,而是获取 2D 数组本身,但所做的更改被保留。

void add(int **a,int **b,int r,int c,int **sum)
{
      static int i=0,j=0;
      if(i>=r)
      {
          return;// sum;
      }
      else
      {
          if(j<c)
          {
              sum[i][j] = a[i][j]+b[i][j];
              j++;
              add(a,b,r,c,sum);
          }
          j=0;
          i++;
          add(a,b,r,c,sum);
      }
}

但是,如果参考添加函数,我会得到垃圾值。

void add(int **a,int **b,int r,int c,int ***sum)
{
      static int i=0,j=0;
      if(i>=r)
      {
          return;
      }
      else
      {
          if(j<c)
          {
              (*sum)[i][j] = a[i][j]+b[i][j];
              j++;
              add(a,b,r,c,sum);
          }
          j=0;
          i++;
          add(a,b,r,c,sum);
      }
}

#include<stdio.h>
#include<stdlib.h>
void input(int **a,int r,int c)
{
     for(int i=0;i<r;i++)
    {
        for(int j=0;j<c;j++)
        {
            scanf("%d",&a[i][j]);
        }
    }
}
void dynamic(int ***a,int r,int c)
{
    *a = (int**)malloc(sizeof(int*)*r);
    for(int i=0;i<r;i++)
    {
        (*a)[i] = (int*)malloc(sizeof(int)*c);
    }

}
int** matmul(int **a,int r1,int c1,int **b,int r2,int c2,int **c)
{
    static int i=0,j=0,k=0;
    if(i>r1)
    {
        return c;
    }
    else
    {

        if(j<c2)
        {
            if(k==0)
             {
                c[i][j]=0;
             }
            if(k<r2)
            {
                c[i][j]+= a[i][k]*a[k][j];
                k++;
                printf("product = %d ",c[i][j]);
                matmul(a,r1,c1,b,r2,c2,c);
            }
            k=0;
            j++;
            matmul(a,r1,c1,b,r2,c2,c);
        }
        j=0;
        i++;
        matmul(a,r1,c1,b,r2,c2,c);
    }
}
void freeing(int **arr,int r,int c)
{
    for(int i=0;i<r;i++)
    {
        free(arr[i]);
    }
    free(arr);
}

void print_array(int **a,int r,int c)
{
    for(int i=0;i<r;i++)
    {
        for(int j=0;j<c;j++)
        {
            printf("%d ",a[i][j]);
        }
        printf("\n");
    }
    return;
}

void main()
{
    int **a,**b,r1,c1,r2,c2,i,j,**product;
    printf("Enter the number of rows and columns in first matrix\n");
    scanf("%d%d",&r1,&c1);

    printf("Enter the number of rows and columns in first matrix\n");
    scanf("%d%d",&r2,&c2);
    if(r2==c1)
    {
        printf("Enter First array\n");
        dynamic(&a,r1,c1);
        input(a,r1,c1);


        printf("Enter Second array\n");
        dynamic(&b,r2,c2);
        input(b,r2,c2);

        printf("First matrix is\n");
        print_array(a,r1,c1);

        printf("Second matrix is\n");
        print_array(b,r2,c2);

        dynamic(&product,r1,c2);
        {
            if(product[0]==NULL)
            {
                printf("memory not allocated\n");
            }
        }
        product=matmul(a,r1,c1,b,r2,c2,product);
        printf("Product of 2 matrices are\n");
        print_array(product,r1,c2);

        freeing(a,r1,c1);
        freeing(b,r2,c2);
        freeing(product,r1,c2);
    }
    else
    {
        printf("Array multiplication not possible! enter correct dimension");
    }

}



我试图编写用于动态分配 2D 数组的函数,但没有获取输入值,我将 2d ARRAY 的地址传递到动态函数中,这次它起作用了。我对添加函数应用了相同的逻辑,但我没有得到正确的结果,当我直接传递 2D 数组时,它起作用了,可能是什么原因。此外,我希望数组的维度由用户定义。

数组 C 指针 多维数组 按引用传递

评论

0赞 Some programmer dude 3/6/2023
传递指针以便能够访问(或修改)指针所指向的内容。
0赞 Some programmer dude 3/6/2023
顺便问一下,你为什么要递归调用?你的实际任务或练习是什么?请记住,一旦您更改了局部变量,它们就不会被“重置”或再次初始化,您只能在程序中调用一次addstaticadd
3赞 chux - Reinstate Monica 3/6/2023
'“如果我直接将 2d 数组作为参数,那么它就不会接受输入。” -->发布该代码。
1赞 Some programmer dude 3/6/2023
也许你问的问题是因为数组数组与指向指针的指针不同?虽然数组衰减到指向其第一个元素的指针,但在嵌套数组的情况下,这种衰减只发生在外部数组上。因此,如果你有例如,那么将衰减为具有 的类型。不会再发生衰变。int a[5][10];a&a[0]int (*)[10]
1赞 Vlad from Moscow 3/6/2023
@Pranav Vasishta 提供一个最小的完整程序来重现问题。

答:

1赞 David Ranieri 3/6/2023 #1

此时:

(*sum)[i][j] = a[i][j]+b[i][j];

编译器不知道数组的维度,因为函数:

void add(int **a,int **b,int r,int c,int ***sum)

没有提供此类信息,换句话说,指向指针的指针和 2D 数组不是同一类型,您不能指望编译器从int(*)[dim]int [][dim]int **

从 C99 开始,您可以使用 VLA(可变长度阵列)来解决这个问题:

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

void add(int rows, int cols, int (*a)[cols], int (*b)[cols], int (*sum)[cols])
{
    for (int row = 0; row < rows; row++)
    {
        for (int col = 0; col < cols; col++)
        {
            sum[row][col] = a[row][col] + b[row][col];
        }
    }
}

int main(void)
{
    int rows = 2, cols = 3;
    int ( *a )[cols] = malloc(sizeof(int) * rows * cols);
    int ( *b )[cols] = malloc(sizeof(int) * rows * cols);
    int (*sum)[cols] = malloc(sizeof(int) * rows * cols);

    srand((unsigned)time(NULL));
    for (int row = 0; row < rows; row++)
    {
        for (int col = 0; col < cols; col++)
        {
            a[row][col] = rand() % 100;
            b[row][col] = rand() % 100;
        }
    }
    add(rows, cols, a, b, sum);
    for (int row = 0; row < rows; row++)
    {
        for (int col = 0; col < cols; col++)
        {
            printf("%d + %d = %d, ", a[row][col], b[row][col], sum[row][col]);
        }
        printf("\n");
    }
    free(a);
    free(b);
    free(sum);
    return 0;
}

请注意,VLA 在 C11 中是可选的

评论

0赞 Pranav Vasishta 3/7/2023
但我希望数组的维度由用户定义。
0赞 David Ranieri 3/7/2023
你可以定义它们:你就完成了。scanf("%d", &rows); scanf("%d", &cols);
2赞 Vlad from Moscow 3/6/2023 #2

调用这两个递归函数的结果没有区别。

但是,这些函数有一个严重的缺点:如果多次调用它们,它们将不起作用,因为在调用函数后,静态变量的值不会重置为静态变量。i0

声明参数也没有多大意义,例如sum

int **sum

因为该函数不会更改用作参数的指针本身。它更改指针指向的数据。

使用您的方法,可以按以下方式定义递归函数,如下面的演示程序所示。该函数被调用两次,以确保在第一次调用函数后,其静态变量被正确重置,并且可以第二次调用该函数。

在程序中,没有使用动态分配的数组来简化代码。

#include <stdio.h>

void add( int **a, int **b, unsigned int r, unsigned int c, int **sum )
{
    static unsigned int i = 0, j = 0;

    if (i < r && j != c)
    {
        sum[i][j] = a[i][j] + b[i][j];
        if (++j == c)
        {
            j = 0;
            ++i;
        }

        add( a, b, r, c, sum );
    }
    else
    {
        i = 0;
    }
}

int main( void )
{
    enum { r = 2, c = 3 };

    int a0[c] = { 1, 2, 3 };
    int a1[c] = { 4, 5, 6 };
    int * aa[r] = { a0, a1 };
    int ** a = aa;

    int b0[c] = { 10, 20, 30 };
    int b1[c] = { 40, 50, 60 };
    int * bb[r] = { b0, b1 };
    int ** b = bb;

    int s0[c];
    int s1[c];
    int * ss[r] = { s0, s1 };
    int ** sum = ss;

    add( a, b, r, c, sum );

    for (unsigned int i = 0; i < r; i++)
    {
        for (unsigned int j = 0; j < c; j++)
        {
            printf( "%d ", sum[i][j] );
        }
        putchar( '\n' );
    }

    putchar( '\n' );

    for (unsigned int  j = 0; j < c; j++)
    {
        s0[j] = 0;
        s1[j] = 0;
    }

    add( a, b, r, c, sum );

    for (unsigned int i = 0; i < r; i++)
    {
        for (unsigned int j = 0; j < c; j++)
        {
            printf( "%d ", sum[i][j] );
        }
        putchar( '\n' );
    }
}

程序输出为

11 22 33
44 55 66

11 22 33
44 55 66

可以看出,该函数每次被调用时都能正常工作。

函数的参数 和 具有无符号整数类型,而不是因为将它们声明为具有有符号整数类型是没有意义的。虽然一般来说,最好不要使用类型,而是使用类型。rcunsigned intintunsigned intsize_t

评论

0赞 Vlad from Moscow 3/7/2023
@DavidRanieri我将程序编译为C++程序:)我更改了 r 和 c 的声明。
0赞 Pranav Vasishta 3/7/2023
但我希望数组的维度由用户定义。
0赞 Vlad from Moscow 3/7/2023
@PranavVasishta 这只是一个演示程序。您可以使用可变长度数组或动态分配数组。问题是什么?