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

问题描述 投票:0回答:2

在此函数定义中,我采用了二维数组地址的参数。

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);

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

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

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");
    }

}



我尝试编写一个用于动态分配二维数组的函数,但没有获取输入值,我将二维数组的地址传递给动态函数,这次它成功了。我对 add 函数应用了相同的逻辑,但我没有得到正确的结果,当我直接传递二维数组时它起作用了,这可能是什么原因。我还希望数组的维度由用户定义。

arrays c pointers multidimensional-array pass-by-reference
2个回答
2
投票

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

然而,这些函数有一个严重的缺点:如果调用多次,它们将无法工作,因为静态变量

i
的值在函数调用后不会重置为
0

也没有什么意义声明参数

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

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

函数的参数

r
c
具有无符号整数类型
unsigned int
而不是
int
因为将它们声明为具有符号整数类型是没有意义的。虽然一般来说,而不是类型
unsigned int
使用类型
size_t
会更好。


1
投票

此时:

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

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

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

没有提供此类信息,换句话说,指向指针的指针和二维数组的类型不同,您不能期望编译器从

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 中是可选的

© www.soinside.com 2019 - 2024. All rights reserved.