c언어 개인 강습을 진행하다가 

구구단용 배열을 main함수 밖 사용자 정의 함수로 초기화하고, main함수 밖 사용자 정의 함수로 출력하라

라는 지시를 했는데, 나도 막혀버렸다^^;;

2차원 배열이라 2중 포인터를 사용하면 될 것이라고 생각했는데 한가지 논리적 오류가 있었던 것 같다.


#include <stdio.h>

#include <stdlib.h>

 

int fFunction (int **ppPointer)

{

    ppPointer[0][0]=3;

    printf("fFunction : %d n", ppPointer[0][0]);

    return 0;

}

 

int main(void)

{

    int mArr[2][2];

    mArr[0][0] = 2;

    fFunction(mArr);

    printf("main : %d n", mArr);

    return 0;

}


첫번째 시도한 소스코드다.

일단 "배열의 이름이 2중 포인터이기 때문에 2중 포인터로 받으면 되겠지?" 라는 1차원적인 생각으로 작성한 코드다.


Cap 2016-12-15 16-42-56-360.png

[Fig. 1] Error....


여기에 대해 좀 여러가지 케이스로 삽질(?)을 시도하여 정리한 포스팅을 발견했다.1)

포스팅에서는 함수가 넘겨받은 변수 자체로부터 배열 차원들을 알아낼 수 있는 방식으로 전달해줘야 한다고 제시한다.


#

int 형 4 x 4 배열이 있다고 가정해볼 때, 배열의 총 크기는 4 x 4 x 4 = 64 Byte 가 된다. 


Cap 2016-12-15 17-25-13-449.png

[Fig. 2] 4 x 4 matirx


이것을 2중 포인터로 지목을 하게 되는 경우 

전달받는 포인터 입장에서는, 

"인자의 정확한 크기는 알겠는데... 2차원 배열이란 것도 알겠는데... 대체 행과 열의 수가 어떻게 되는지도 모르겠다."는 식으로 컴파일 에러를 발생시킨다.


2차원 배열로 표현된 메모리 공간은 사실 1줄로 표현 할 수 있는데,


Cap 2016-12-15 17-27-54-848.png

[Fig. 3] mArr 메모리 상태


ppPointer 입장에서는 1줄의 길이를 모르니 [1][0]이 어느 위치에 있는 놈인지 인식을 못한다는 것이다.


Cap 2016-12-15 17-30-17-215.png

[Fig. 4] ppPointer가 인식하고 있는 메모리 상태


요컨데 2차원 배열로 가르켰고, 크기를 제시했다면, 컴파일러는 행열의 수를 2 x 8로 인식을  할 수도 있고 1 x 16 나 8 x 2로 인식할 수도 있다는 거다.


그래서 포인터에게 행이나 열의 길이 중 하나의 값을 제시해 줘야 한다.

그러면 적어도 나머지 길이는 알 수 있게 되니, 컴파일 에러가 나지 않는다.


int fFunction (int ppPointer[2][2])

{

    ppPointer[0][0]=3;

    printf("fFunction : %d n", ppPointer[0][0]);

    return 0;

}

 

int main(void)

{

    int mArr[2][2];

    mArr[0][0] = 2;

    fFunction(mArr);

    printf("main : %d n", mArr);

    return 0;

}


자 이러면 컴파일 에러도 나지 않고 결과값도 정상적으로 출력되는 것을 볼 수 있다.

그런데 이것은 Call-by-reference 가 아니라 Call-by-value가 아닌가요? 란 질문을 할 수 있다.


#include <stdio.h>

#include <stdlib.h>

 

int fFunction (int ppPointer[2][2])

{

    ppPointer[0][0]=3;

    printf("fFunction : %d n", ppPointer[0][0]);

    printf("fFunction : %d n", sizeof(ppPointer));

    return 0;

}

 

int main(void)

{

    int mArr[2][2];

    mArr[0][0] = 2;

    fFunction(mArr);

    printf("main : %d n", mArr);

    printf("main : %d n", sizeof(mArr));

    return 0;

}


자 그래서 소스코드에 약간의 조미료를 쳐봤다.

코드를 보면 알겠지만 main 함수에서 선언된 배열(mArr)의 크기와 fFunction 함수에서 선언된 배열(ppPointer)의 크기를 sizeof함수를 이용해서 출력하라고 하고 있다.

이걸로 ppPointer가 배열인지, 포인터인지 알 수 있다.


값이 16이 나오면 ppPointer가 Call-by-value로 활용된다는 말이 되고, 

값이 4가 나오면 ppPointer가 Call-by-reference로 활용되고 있다는 말이 된다.



성공사례 1 :

// 포인터 표시를 배열의 형식으로 선언

// 보기와는 다르게 Call-by-reference 

int fFunction (int ppPointer[2][2])

int fFunction (int ppPointer[  ][2])

성공사례 2 :

// 포인터 자체를 배열로 선언하는 형식

int fFunction (int (*ppPointer)[2]) // 얘는 문법상 (ppPointer[])[2] 로 치환될 수 있음


실패사례 : 

int fFunction (int **ppPointer       // 2차원 포인터이긴 한데, 배열 형식은 아님

int fFunction (int ppPointer  [2] )  // 1차원 포인터 배열 형식임

int fFunction (int *(ppPointer) [2] )  // 1차원 포인터 배열 형식임


이렇게 배열을 전달하는 방식은 항상 '길이'가 중요하다고 할 수 있다.

3차원 배열의 경우는 잘 쓰지 않으니 본 포스팅에서는 skip한다. 대신 이와 관련된 레퍼런스를 링크하니 참고하기 바란다.3)


Reference


1) 스피비, "2차원 배열을 매개변수로 넘길 때", skmagic.tistory.com/entry/2차원-배열을-매개변수로-넘길-때, 2011.03.07

2) kkikkodev, "[C언어>실습] 2차원 배열을 함수의 인자로 전달하기", http://kkikkodev.tistory.com/200, 2015.08.02

3) 스카웃, "[스카웃 C언어 강좌] 17-9 함수의 인자로 다차원 배열을 전달해보자", http://blog.naver.com/PostView.nhn?blogId=skout123&logNo=50129573552, 2011.12.21

번호 제목 글쓴이 날짜 조회 수
28 [Tip] VC++ express 2012 file 심플디 2018.06.28 25
27 [Tip] VC++ express 2010 file 심플디 2018.06.28 23
26 [C] 계절학기 강의자료 : 2주차 Reference file 심플디 2018.06.28 26
25 [C] 계절학기 강의자료 : 1주차 Reference file 심플디 2018.06.28 32
24 [Tip] C언어 공부법과 책추천 [퍼옴] 심플디 2018.06.04 25
23 scanf_s 사용하지 않는 방법 심플디 2018.02.01 25
22 [C] NXT를 이용하여 2m를 움직이는 로봇을 제시하시오. (문제제시) 심플디 2016.12.24 24
21 [C] 2중 for문과 2중 while문을 이용하여 구구단 결과 출력하기 (문제제시) [4] 심플디 2016.12.24 29
20 [C] ASCII code를 이용하여 문자 및 숫자를 가려내기 (문제제시) 심플디 2016.12.24 24
19 [C] AutoCAD에서 직사각형을 보여주는 파일 출력하기, 불러오기 (문제제시) 심플디 2016.12.24 25
18 [C] 적분 프로그래밍 (문제제시) [2] 심플디 2016.12.24 26
17 [C] 이름을 입력받고 해당 배열을 동적할당 시키는 예제 (문제제시) 심플디 2016.12.24 24
16 [C] 거품 정렬 -1 (syj) 노예 2016.12.18 21
15 [C] 선택 정렬 - 1 SYJ) 노예 2016.12.18 23
» [C] 2차원 배열을 함수로 전달하는 방안 [1] file 심플디 2016.12.16 24
13 [C] 20161206 송유준 강의자료 Day 01~Day 03 file 심플디 2016.12.07 3
12 [알고리즘] 시각화에 좋은 사이트 file 심플디 2016.08.08 26
11 [ERROR] VC++2015 "fatal error LNK1168 ~.exe을(를) 쓰기용으로 열 수 없습니다." 에러를 해결했다. 심플디 2016.01.23 46
10 [ERROR] VC++2015 "fatal error LNK1168 ~.exe을(를) 쓰기용으로 열 수 없습니다." 에러를 해결해보기 위해 삽질해 보았다. file 심플디 2015.11.27 101
9 [C] 마름모 출력 file 심플디 2013.06.23 5764