'복잡한 포인터'에 해당되는 글 1건

  1. 2007/09/18 복잡한 포인터 선언 이해하기 (3)

회사에 있는 MircoSoftware ( <월간>마소 ) 8월호를 읽던중 반가운 글을 보았습니다.
바로 이전 포스팅인 포인터에 대한 글이였는데, 제목이 무려 "신입 개발자를 위한" 복잡한 포인터 선언 이해하기. 포인터의 난해함때문에 고민을 했던적이 있던지라 반가운 글이였습니다.

신입 개발자를 위한
복잡한 포인터 선언 이해하기
신영진 | pop@jiniya.net | http://www.jiniya.net

  개발자 커뮤니티의 C언어 게시판에 자주 등장하는 질문 가운데 하나가 바로 복잡한 포인터 선언문 해석에 대한 것이다. 대부분의 초보 개발자나 학생들은 이를 막연히 외우려고 노력한다. 'int *a[3]은 int 포인터를 저장하는 배열', 'int (*a)[3]은 int 배열에 대한 포인터' 라는 식으로 암기하는 것이다.
  하지만 이렇게 외운 지식은 그 형태가 조금만 달라져도 무용지물이 되고 만다.
  그렇다면 어떻게 해야 이러한 선언문을 쉽게 해석할 수 있을까? 간단하다. 다음의 규칙만 이해하면 된다.
  복잡한 선언을 정확하게 이해하기 위한 첫 단계는 선언문 내부에 나타나는 각 요소의 정확한 의미를 이해하는 것이다.
  아래 표에는 선언문 내부에 등장하는 각 구성요소의 의미와 사용 예가 나와 있다. 이처럼 선언문을 해석할 때 영어를 활용하면 훨씬 간편하게 의미를 이해할 수 있다. 따라서 각 기호에 맞는 영어 표현도 함께 알아두는 것이 좋다.

기호

표현

의미

*

pointer to 특정 대상체를 가리키는 포인터

int *a;
a는 int 형을 가리키는 포인터다.

[]

array of 특정 대상체를 저장하는 배열

int a[3];
a는 int를 3개 저장할 수 있는 배열이다.

()

function 인자를 받고 값을 리턴하는 함수

int a();
a는 인자가 없고 int를 반환하는 함수다


  다음으로 이해해야 할 것은 선언문을 해석하는 순서다.
  선언문은 선언 대상이 되는 변수명에서 시작해 오른쪽으로 가면서 해석한다. 선언문의 끝이나 오른쪽 괄호를 만나면 방향을 바꿔 왼쪽으로 가면서 해석한다. 왼쪽으로 가면서 해석을 하다 왼쪽 괄홀르 만나면 다시 오른쪽으로 가면서 해석한다. 이렇게 해서 선언문의 가장 왼쪽 끝에 도달하면 해석이 마무리된다.

표현식 해석 순서
해석 결과
int **a; a => a; => *a; => **a; => int **a;
a is a pointer to pointer to int
a는 int를 가리키는 포인터의 포인터다.
int *a[3]; a => a[3] => a[3]; => *a[3] => int *a[3];
a is an array of 3 pointer to int
a는 int를 가리키는 포인터를 세 개 저장하는 배열이다.
int (*a)[3]; a => a) => (*a) => (*a)[3]; => int (*a)[3];
a is a pointer to array of 3 int
a는 int 세 개를 저장하고 있는 배열을 가리키는 포인터다.
int *(*(*fp1)(int))[10];

fp1 => fp1) => (*fp1) => (*fp1)(int) => (*fp1)(int)) => (*(*fp1)(int)) => (*(*fp1)(int))[10]; => *(*(*fp1)(int))[10]; => int *(*(*fp1)(int))[10];

fp1 is a pointer to function that takes an int as an argument and returns a pointer to an array of 10 pointers to ints.
fp1은 int를 인자로 받고 int에 대한 포인터를 열 개 저장하는 배열을 가리키는 포인터를 리턴하는 함수에 대한 포인터다.
char *(*(**foop[][8])())[]; foo[] => foo[][8]) => *foo[][8]) => (**foo[][8]) => (**foo[][8])()) => *(**foo[][8])()) => (*(**foo[][8])())[]; => char *(*(**foo[][8])())[];
foo is an array of array of 8 pointer to pointer to function that returns a pointer to array of pointer to char.
foo는 char를 가리키는 포인터를 저장하는 배열을 가리키는 포인터를 리턴하는 함수에 대한 포인터를 가리키는 포인터를 8개 저장할 수 있는 배열에 대한 배열이다.


/*
역시 포인터는 어려운 존재입니다 -__-;
이 글에서 소개되어있는 해석하는 방법은 "영어"를 사용하는 사람들을 위한 해석방법이군요, 문장의 순서가 우리나라와는 다르기 때문에 우리나라에 맞게 적용하기 위해서는 반대 방법으로 해야할듯 합니다. 이를테면 괄호의 맨 밖부터 시작해서 왼쪽부터 오른쪽으로 가면서 끝을 만나면 그 내부의 괄호안에 들어가서 왼쪽에서 오른쪽으로 진행하는 식으로.. (실제로 해보시면 회색처리된 한글 해석순서와 비슷하다는걸 알 수 있습니다. 네 비슷입니다 =_=, 완전히 적용시키기엔 무리가 있네요 [][8] 같은경우는 오른쪽에서 왼쪽으로 가야 합니다.

PS. micro Software의 2007년 8월호 325page의 글을 옮겨 적은 것 입니다. 문제가 될경우 알려주시면 삭제하겠습니다.
*/
Posted by Mastojun