C语言二维数组和指针有关问题

想了很久不知道问题出在哪。


#define YOKO_MAX 20
#define TATE_MAX 20
int* creatMap(void);
int main( void )
{
    int* field[TATE_MAX][YOKO_MAX] = creatMap();
    for (int i = 0; i < TATE_MAX; i++)
    {
        for (int j = 0; j < YOKO_MAX; j++)
        {
            printf("%d\t", *(*(field + i) + j));
        }
    }
}

int* creatMap(void)
{

    int a[TATE_MAX][YOKO_MAX];
    int(*p)[TATE_MAX][YOKO_MAX] = &a;
    int i, j;
    for (int i = 0; i < TATE_MAX; i++)
    {
        for (int j = 0; j < YOKO_MAX; j++)
        {
            if (i == 0 || i == TATE_MAX - 1)
            {
                a[i][j] = 1;
            }
            else if (j == 0 || j == YOKO_MAX - 1)
            {
                a[i][j] = 1;
            }
            else
            {
                a[i][j] = 0;
            }
        }
    }

    return p[TATE_MAX][YOKO_MAX];
}

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

#define YOKO_MAX 20
#define TATE_MAX 20

int** createMap(void);

int main(void)
{
    int** field = createMap();

    for (int i = 0; i < TATE_MAX; i++)
    {
        for (int j = 0; j < YOKO_MAX; j++)
        {
            printf("%d    ", field[i][j]);
        }
        printf("\n");
    }

    // 释放内存
    for (int i = 0; i < TATE_MAX; i++)
    {
        free(field[i]);
    }
    free(field);

    return 0;
}

int** createMap(void)
{
    int** a = (int**)malloc(TATE_MAX * sizeof(int*));
    for (int i = 0; i < TATE_MAX; i++)
    {
        a[i] = (int*)malloc(YOKO_MAX * sizeof(int));
        for (int j = 0; j < YOKO_MAX; j++)
        {
            if (i == 0 || i == TATE_MAX - 1 || j == 0 || j == YOKO_MAX - 1)
            {
                a[i][j] = 1;
            }
            else
            {
                a[i][j] = 0;
            }
        }
    }

    return a;
}

在creatMap函数中,指针p指向了本地变量a,然后尝试返回p[TATE_MAX][YOKO_MAX],这就导致错误。因为a是一个本地变量,当函数creatMap执行完成时,a将被销毁,因此无法返回指向它的指针,可以试着用一个动态分配的二位数组。
详细可见C技能树:内存动态管理

以下代码存在几个问题:

  1. 在函数声明 int* creatMap(void); 中,应该在函数名后面加上括号 (),表示该函数没有参数。正确的声明应该是 int* creatMap(void);

  2. main 函数中,int* field[TATE_MAX][YOKO_MAX] 的声明是错误的。应该将其修改为 int (*field)[YOKO_MAX] = creatMap();,表示 field 是一个指向整型数组的指针。

  3. creatMap 函数中,局部变量 a 是一个二维数组,但是 p 的类型应该是 int(*)[YOKO_MAX],而不是 int(*)[TATE_MAX][YOKO_MAX]。修改 int(*p)[TATE_MAX][YOKO_MAX] = &a;int (*p)[YOKO_MAX] = a;

  4. creatMap 函数的最后,应该返回指向二维数组首元素的指针,即 return p;

修改后的代码如下:

#include <stdio.h>

#define YOKO_MAX 20
#define TATE_MAX 20

int (*creatMap(void))[YOKO_MAX];

int main(void)
{
    int (*field)[YOKO_MAX] = creatMap();
    for (int i = 0; i < TATE_MAX; i++)
    {
        for (int j = 0; j < YOKO_MAX; j++)
        {
            printf("%d\t", field[i][j]);
        }
        printf("\n");
    }

    return 0;
}

int (*creatMap(void))[YOKO_MAX]
{
    static int a[TATE_MAX][YOKO_MAX];
    int (*p)[YOKO_MAX] = a;

    for (int i = 0; i < TATE_MAX; i++)
    {
        for (int j = 0; j < YOKO_MAX; j++)
        {
            if (i == 0 || i == TATE_MAX - 1 || j == 0 || j == YOKO_MAX - 1)
            {
                a[i][j] = 1;
            }
            else
            {
                a[i][j] = 0;
            }
        }
    }

    return p;
}

上述代码修复了函数声明、指针类型和数组访问的问题,并输出了生成的地图数组。