2014-12-03 5 views
-2

2D 배열을 함수에 전달하고 main에서 배열을 직접 변경하려면 참조로 전달해야합니다. 컴파일을 시도 할 때 스위치 케이스에 error: expected expression before {이 표시됩니다. (boardSize = 10이지만 컴파일 시간에는 알려지지 않음)참조로 2D 배열 전달

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

+0

http://stackoverflow.com/a/26877227/971127 – BLUEPIXY

+0

'void fillBoard (int board [] [boardsize]); ' – ooga

답변

1

이렇게하는 데는 여러 가지 방법이 있습니다. 열쇠는 어디에서 다루고 있는지 추적하는 것입니다. single 또는 double 포인터를 사용하여 board을 전달하고 채울 수 있습니다. 모든 요소를 ​​추적하는 방법에 따라 다릅니다. (2 차원 배열은 요소를 참조 할 때 편의성을 제공하지만 모든 값은 메모리에서 순차적이며 1 차원 참조 및 오프셋을 사용하여 액세스 할 수 있습니다).

numeric 어레이에 메모리를 할당 할 때 중요한 제안 사항이 있습니다. 초기화되지 않은 값 (정의되지 않은 동작)에 대한 액세스 또는 참조 해제를 방지하려면 항상 배열의 요소를 초기화해야합니다. 이렇게하는 간단한 방법은 malloc 대신 calloc으로 할당하는 것입니다. calloc을 할당하고은 모든 값을 zero (NULL)으로 초기화합니다.

또한 프로그램 수명 동안 할당 한 메모리를 추적해야하며 더 이상 필요하지 않을 때 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]; 
} 

출력하십시오 2-D array 이후

$ ./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.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}}; 

을에이 함수를 줄일 수 있습니다 유사한 기능을 가진

fillBoard (&board); 

: 함수에 배열의 (a 3 성급 프로그래머가되는) : 때문에 포인터 붕괴 (board[10][10] =>board[*][10])에

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)); 
} 

, 당신이 의도 한대로 함수가 성공적으로 메모리를 복사에도 불구하고, incompatible pointer type 경고 메시지가 나타납니다. 경고없이 컴파일되지 않는 코드는 실제로 사용해서는 안됩니다.