2014-12-03 131 views
-2

我希望能夠傳遞一個二維數組到一個函數,並讓它直接在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; 
    } 
} 
+2

'int **'不等於'int [N] [M]'。一個是指針指針,另一個是數組數組。 – WhozCraig 2014-12-03 17:39:14

+0

http://stackoverflow.com/a/26877227/971127 – BLUEPIXY 2014-12-03 17:39:16

+0

'void fillBoard(int board [] [boardsize]);' – ooga 2014-12-03 17:41:52

回答

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] =>board[*][10]),將收到的incompatible pointer type警告,儘管如預期的函數成功複製存儲。在實踐中不應該依賴不經過警告編譯的代碼。