通过引用传递2D数组

时间:2014-12-03 17:33:44

标签: c arrays 2d pass-by-reference

我希望能够将2D数组传递给函数,并让它直接更改main中的数组,因此通过引用传递。当我尝试编译时,我在切换案例中得到error: expected expression before {。 (boardSize = 10,但在编译时不知道)

void fillBoard(int **, int);

int main() {
    int **board = malloc(sizeof(int *) * boardSize);
    fillBoard(board, boardSize);
}

void fillBoard(int **board) {
    int i, *row = malloc(sizeof(int) * boardSize);
    for (i=0; i<boardSize; i++) {
        board[i] = malloc(sizeof(int) * boardSize);
        switch(i) {
            case 1: row = {1,0,1,0,1,1,0,0,1,0}; break;
            default: row = {0,0,0,0,0,0,0,0,0,0}; break;
        }
        board[i] = row;
    }
}

1 个答案:

答案 0 :(得分:1)

有很多不同的方法可以做到这一点。关键是要跟踪你在哪里解决的问题。您可以使用singledouble指针来传递和填充board,这完全取决于您希望如何跟踪元素。 (虽然二维数组提供了引用元素的便利,但所有值在内存中是顺序的,并且可以使用一维引用和偏移进行访问)。

numeric数组分配内存时,有一个重要的建议。您必须始终初始化阵列的所有元素,以防止尝试访问或取消引用未初始化的值(未定义的行为)。执行此操作的简单方法是使用calloc而不是malloc进行分配。 calloc分配将所有值初始化为zeroNULL)。

还要注意需要跟踪在程序生命周期内分配的内存以及free内存不再需要时的内存。这样可以防止内存泄漏。在如下所示的一小段代码中,当程序退出时释放内存。如果这是某些较大代码的一部分,那么当不再需要数据时,您需要释放boardboard2

使用原始数组的示例如下:

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

#define boardSize 10

void fillBoard_p (int *a);
void fillBoard_p2p (int **a);

int main() {
    int i = 0;
    int j = 0;

    /* declaring board as an integer pointer */
    int *board = calloc (boardSize * boardSize, sizeof (*board));

    /* declaring board as a pointer to pointer */
    int **board2 = calloc (boardSize, sizeof (*board2));
    for (i = 0; i < boardSize; i++) {
        board2[i] = calloc (boardSize, sizeof (**board2));
    }

    fillBoard_p (board);
    fillBoard_p2p (board2);

    printf ("\nboard as an integer pointer:\n");
    for (i = 0; i < boardSize * boardSize; i++) {
        if (i % boardSize == 0)
            printf ("\n %d", board[i]);
        else
            printf (" %d", board[i]);
    }

    printf ("\n");

    printf ("\nboard2 as an pointer to integer pointer:\n\n");
    for (i = 0; i < boardSize; i++) {
        for (j = 0; j < boardSize; j++) {
            printf (" %d", board2[i][j]);
        }
        printf ("\n");
    }    
    printf ("\n");

    return 0;
}

void fillBoard_p(int *a) {
    // 0=WHITE, 1=BLACK
    int i = 0;
    int j = 0;
    int b [][boardSize] = {
        {1,0,1,0,1,1,0,0,1,0}, 
        {1,0,1,1,0,0,1,1,1,0}, 
        {0,0,1,0,1,0,1,0,1,1},
        {1,1,0,1,1,0,1,0,0,0},
        {0,0,1,0,0,0,1,1,0,1},
        {1,1,0,1,1,0,0,1,1,0},
        {0,0,1,0,0,1,1,0,1,1},
        {0,0,1,0,0,1,0,0,0,0},
        {1,1,1,1,0,0,1,1,1,1},
        {0,1,0,0,1,1,0,0,0,1}
    };

    for (i = 0; i < boardSize; i++)
        for (j = 0; j < boardSize; j++)
            a[i*boardSize+j] = b[i][j];
}

void fillBoard_p2p (int **a) {
    // 0=WHITE, 1=BLACK
    int i = 0;
    int j = 0;
    int b [][boardSize] = {
        {1,0,1,0,1,1,0,0,1,0}, 
        {1,0,1,1,0,0,1,1,1,0}, 
        {0,0,1,0,1,0,1,0,1,1},
        {1,1,0,1,1,0,1,0,0,0},
        {0,0,1,0,0,0,1,1,0,1},
        {1,1,0,1,1,0,0,1,1,0},
        {0,0,1,0,0,1,1,0,1,1},
        {0,0,1,0,0,1,0,0,0,0},
        {1,1,1,1,0,0,1,1,1,1},
        {0,1,0,0,1,1,0,0,0,1}
    };

    for (i = 0; i < boardSize; i++)
        for (j = 0; j < boardSize; j++)
            a[i][j] = b[i][j];
}

<强>输出:

$ ./bin/fillboard

board as an integer pointer:

 1 0 1 0 1 1 0 0 1 0
 1 0 1 1 0 0 1 1 1 0
 0 0 1 0 1 0 1 0 1 1
 1 1 0 1 1 0 1 0 0 0
 0 0 1 0 0 0 1 1 0 1
 1 1 0 1 1 0 0 1 1 0
 0 0 1 0 0 1 1 0 1 1
 0 0 1 0 0 1 0 0 0 0
 1 1 1 1 0 0 1 1 1 1
 0 1 0 0 1 1 0 0 0 1

board2 as an pointer to integer pointer:

 1 0 1 0 1 1 0 0 1 0
 1 0 1 1 0 0 1 1 1 0
 0 0 1 0 1 0 1 0 1 1
 1 1 0 1 1 0 1 0 0 0
 0 0 1 0 0 0 1 1 0 1
 1 1 0 1 1 0 0 1 1 0
 0 0 1 0 0 1 1 0 1 1
 0 0 1 0 0 1 0 0 0 0
 1 1 1 1 0 0 1 1 1 1
 0 1 0 0 1 1 0 0 0 1

此外,由于2-D array按顺序存储在内存中,您可以利用这一事实并利用memcpy(在string.h中)填充传递给函数的数组。这可以将您的功能降低到:

void fillBoard_mc (int *a) {
    // 0=WHITE, 1=BLACK
    int b [][boardSize] = {
        {1,0,1,0,1,1,0,0,1,0}, 
        {1,0,1,1,0,0,1,1,1,0}, 
        {0,0,1,0,1,0,1,0,1,1},
        {1,1,0,1,1,0,1,0,0,0},
        {0,0,1,0,0,0,1,1,0,1},
        {1,1,0,1,1,0,0,1,1,0},
        {0,0,1,0,0,1,1,0,1,1},
        {0,0,1,0,0,1,0,0,0,0},
        {1,1,1,1,0,0,1,1,1,1},
        {0,1,0,0,1,1,0,0,0,1}
    };
    memcpy (a, b, boardSize * boardSize * sizeof (int));
}

如果不是编译器和pointer decay的特殊性,您可以简单地使用静态声明的数组,例如:

int board[boardSize][boardSize] = {{0}};

将数组的地址传递给您的函数(成为 3星级程序员):

fillBoard (&board);

具有类似于:

的功能
void fillBoard (int *a[][boardSize]) {
    // 0=WHITE, 1=BLACK
    int b [][boardSize] = {
        {1,0,1,0,1,1,0,0,1,0}, 
        {1,0,1,1,0,0,1,1,1,0}, 
        {0,0,1,0,1,0,1,0,1,1},
        {1,1,0,1,1,0,1,0,0,0},
        {0,0,1,0,0,0,1,1,0,1},
        {1,1,0,1,1,0,0,1,1,0},
        {0,0,1,0,0,1,1,0,1,1},
        {0,0,1,0,0,1,0,0,0,0},A
        {1,1,1,1,0,0,1,1,1,1},
        {0,1,0,0,1,1,0,0,0,1}
    };
    memcpy (a, b, boardSize * boardSize * sizeof (int));
}

由于指针衰减(board[10][10] =&gt; board[*][10]),您将收到incompatible pointer type警告,尽管该功能已按预期成功复制内存。在实践中不应依赖不经过警告编译的代码。