动态分配矩阵在打印时给出seg错误

时间:2017-11-17 18:59:20

标签: c matrix malloc

此代码通过一系列函数调用来分配矩阵,但是当我打印它时,它会返回分段错误。

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

void mat_init(int** matx);
void pp_init(int** matx);
void p_init(int** matx);
void mat_fill(int** matx);
void mat_print(int** matx);

int main(void)
{
    srand((unsigned)time(NULL));
    int** matrix;
    mat_init(matrix);
    mat_print(matrix);
    return 0;
}

void mat_init(int** matx)
{
    pp_init(matx);
}

void pp_init(int** matx)
{

    matx=malloc(4*sizeof(int*));
    p_init(matx);
}

void p_init(int** matx)
{
    for(int i=0;i<4;i++)
    {
        *(matx+i)=malloc(4*sizeof(int));
    }
    mat_fill(matx);
}

void mat_fill(int** matx)
{
    for(int i=0;i<4;i++)
    {
        for(int j=0;j<4;j++)
        {
            *(*(matx+i)+j)=rand()%5;
        }
    }
    //mat_print(matx);
}

void mat_print(int** matx)
{
    printf("The matrix is:\n");
    for(int i=0;i<4;i++)
    {
        for(int j=0;j<4;j++)
        {
            printf("%1i|",*(*(matx+i)+j));
        }
        puts("");
    }
    puts("");
}

请注意,只有当我使用mat_print()int在main中打印矩阵时才会发生这种情况,如果我在函数mat_fill()中使用它,它可以正常工作,表明它已被正确初始化。 有什么问题?

2 个答案:

答案 0 :(得分:1)

你需要这样做:

int** mat_init(int** matx);
int** pp_init(int** matx);

int main(void)
{
    matrix=mat_init(matrix);
}

int** mat_init(int** matx)
{
    return pp_init(matx);
}

int** pp_init(int** matx)
{
    matx=malloc(4*sizeof(int*));
    p_init(matx);
    return matx;
}

我省略了一些我没有改变的行。另一种选择是:

void mat_init(int*** matx);
void pp_init(int*** matx);

int main(void)
{
    mat_init(&matrix);
}

void mat_init(int*** matx)
{
    pp_init(matx);
}

void pp_init(int*** matx)
{
    *matx=malloc(4*sizeof(int*));
    p_init(*matx);
}

另一件事:你在很多地方都使用了值4。这很危险。改为使用常数。

#define MAT_SIZE 4

void mat_fill(int** matx) {
    for(int i=0;i<MAT_SIZE;i++) {
        for(int j=0;j<MAT_SIZE;j++)

答案 1 :(得分:1)

基本上你正在做的是:

void foo(int a);
{
  a = 6;
}

int main()
{
  int a = 3;
  foo(a);
  printf("a = %d\n", a);  // expecting this to print 6

  return 0;
}

C中的所有内容都是按值传递的,因此这意味着只要将参数传递给函数,就会在该函数中创建它的本地副本,并且其范围仅存在于该函数中;指针也不例外。如果我有这个代码:

void foo (int* ap2)
{
  // there are now 2 pointers in memory that point to the same thing (main's a), namely
  // ap2 on this stack frame and ap1 in the previous stack frame.
  *ap2 = 6;
  // ap2 is local to this function, but it _points_ to the same thing as
  // ap1, so when we dereference it, changes to _what it points to_ are seen
  // outside of this function. But once we return from this function, ap2
  // ceases to exist
}

int main()
{
  int a = 3;
  int* ap1 = &a;
  foo(ap1);
  printf("a = %d\n", a);  // now this prints 6

  return 0;
}

如果你想在一个函数中操纵main的{​​{1}},那么你需要传递一个指向它的指针并在该函数中取消引用它以便修改什么它指向

matx

但正如我在评论中所说,我很少/从未见过三颗星指针。相反,你可以只返回值

void foo (int*** matxp)
{
  // matxp now points to matx in main
  // dereference it here
  *matxp = malloc(4 * sizeof(int*));
}
int main()
{
  int** matx;
  foo(&matx);  // pass the address of matx here, which is an int*** type

  ....

  // don't forget to clean up everything
  return 0;
}