c - 通过引用传递二维数组

标签 c arrays 2d pass-by-reference

我希望能够将二维数组传递给函数,并让它直接更改 main 中的数组,因此通过引用传递。当我尝试编译时,我在 switch case 中收到 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;
    }
}

最佳答案

有很多不同的方法可以做到这一点。关键是要跟踪你在哪里处理什么问题。您可以使用指针来传递和填充board,这完全取决于您想要如何跟踪元素。 (而二维数组为引用元素提供了便利,所有值在内存中都是连续的,并且可以通过一维引用和偏移量进行访问)。

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

还要注意需要跟踪在程序生命周期内分配的内存,并在不再需要时释放内存。这将防止内存泄漏的发生。在如下的一小段代码中,程序退出时会释放内存。如果这是某些较大代码的一部分,则当不再需要数据时,您需要释放 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

此外,由于二维数组按顺序存储在内存中,因此您可以利用这一事实并使用memcpy(在string.c中)。 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));
}

如果不是因为编译器的特殊性和指针衰减,您可以简单地使用静态声明的数组,例如:

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

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

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] => board[*][10]),您将收到不兼容的指针类型 警告,尽管函数按预期成功复制了内存。在实践中不应依赖那些在没有警告的情况下无法编译的代码。

关于c - 通过引用传递二维数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27278043/

相关文章:

Java平滑2D矩形碰撞?

c - 从 C 中的字符串填充二维整数数组

c - 我想知道这个程序中数组的长度是如何计算的?

2d - calayer 对象上的自定义绘制内容看起来相当像素化

c - 我如何使用 gtk 响应

c - 机器之间 "short"的范围是否不同?

javascript - 查找仅包含不同对象的数组

JavaScript 动态扩展/收缩矩阵 - 如何实现?

编译错误 C2099 : initializer is not a constant

c - shmat() 返回的虚拟内存地址指向不同的硬件内存位置