본문 바로가기

Application-level프로그래밍

(C)정적 2차원 배열 전달


우선 1차원 배열을 함수의 파라미터로 받는 경우를 생각해보자.

void f(int a[],int k)
{
...
}

이 경우에 함수 정의내부에서 a[1]=3; 처럼 값을 설정하는 경우, 전달한 배열의 원소도 값이 바뀐다. 이유는 전달한 정보가 배열의 첫번째 원소 주소이기 때문이다. 하지만 사이즈는 []안에 숫자를 넣더라도 알 수 없다.(정확히는 숫자를 넣어주는 형대로 프로토 타입을 만들어도 컴파일러가 무시한다.) 따라서 사이즈를 위한 인자를 전달해줘야 한다. array argument는 call-by-value argument 도 아니고 call-by-reference argument도 아니다. 다만  언급한 것처럼 call-by-reference 와 유사하다. 


 

다음 코드에서 getStatAr() 함수의 리턴값이 이차원 배열의 주소라 하자.
int** PuyoBoard::getStatAr()
{
 int i,j;
 for(i=0;i<BOARD_HEIGHT;++i)
 {
  for(j=0;j<BOARD_WIDTH;++j)
  {
   statAr[i][j]=p[i][j].getStat();
  }
 }
 return (int**)statAr;
}
여기서 statAr 배열은 정적배열이다. 따라서 위 코드의 리턴값은 불충분한 정보를 지닌다.
(동적배열인경우는 여기서 다루지 않는다, 주의)

일반적으로 정적배열은 연속된 위치에 값이 저장되어 있기 때문에, 어느정도 인덱스 정보가 있어야 그 배열을 다른 (배열)포인터가 대입받을 수있다.
예를 들어보면,
int statAr[3][2] 배열을 전달한 것과 int statAr[2][3]배열을 전달한 경우를 비교했을 때, 메모리상의 statAr[1][1]의 위치는 서로 다르다.
정확한 위치에 대입 시키기 위해서는 대입 받는 쪽에서 정확한 캐스팅을 해주어야 한다.

int (*puyo)[6]=(int(*)[6])p2.getB().getStatAr();
 
전달 받을 배열이 정적배열이고 두번째 인덱스는 0부터 5(=6-1)까지 카운터되는 경우 위 코드 처럼 받을 수있다.
위의 코드 대입문에서  (int(*)[6]) 로 캐스팅하는 대신 (int[][6])도 해보자. 결과는 나도 모른다.
또한 int puyo[][6]으로도 테스트해보자.

위의 대입문 코드 대신 int** puyo; 처럼 대입받으면 안된다(내 맘이 아니라 컴파일러가 싫어한다)는 것이 결론이다.
대입문은 함수 프로토 타입에서 파라미터로 정적배열을 받고자 할때에도 똑같이 적용된다는 것을 유의하자.


참고로,이차원 동적배열, 즉 두번의 반복문을 돌면서 할당(하나는 포인터변수들을 위한  할당, 하나는 각 포인터에 대해 배열의 메모리 할당)한 메모리는 1차원상으로 저장이 아니므로 인덱스 정보 없이 int**로 캐스팅하고 대입 받는다.