함수 포인터나 복잡한 선언이 나올 경우 당황하지 않기 위해 쉽게 읽는 법에 대해 다루겠습니다. 일단 가장 먼저 다음 세 개 목록을 외우시기 바랍니다: ||연산자||읽는 법||주의사항|| ||*||a pointer to|| || ||(...)||a function(...) returning||여기서 "..."는 인자 목록(parameter list)임|| ||[N]||array[N] of||여기서 N은 배열 크기를 나타냄|| 복잡한 선언을 읽는 방법은 다음과 같습니다: * 이름(identifier)이 있는 곳부터 차례대로 읽는다. * 읽는 순서는 연산자 결합 순위가 높은 것부터 읽는? 위 표에 나온 연산자는 "읽는 법"에 따라 읽되, 위 표의 괄호는 함수 선언을 위한 것입니다. 연산자 우선 순위를 변경하기 위한 괄호는 읽지 않습니다. 예를 들어 아래 선언을 읽어 봅시다: {{{int *a;}}} 먼저 이름을 찾아야 합니다. 위 선언에서 "a"가 이름이니까, "a"부터 읽어나가면 됩니다. a에서 가장 먼저 결합하는 기호는 "*"입니다. 따라서 위의 표를 참고로 하여 읽으면 다음과 같습니다: {{{a = a pointer to ...}}} 그럼 이제 나머지는 "int"이므로 그냥 읽습니다: {{{a = a pointer to int}}} 즉 "a"는 int를 가리키는 포인터 타입입니다. 좀 더 어려운 예를 들어봅시다. {{{int *(*foo)(int, int);}}} 위 예에서 이름은 "foo"이므로, foo에서부터 읽어 나가면 됩니다. 가장 먼저 결합하는 것은 "foo"와 함께 괄호 안에 있는 "*"입니다. 차례대로 읽는 것을 표로 나타내면 다음과 같습니다 (현재 읽고 있는 부분은 @...@ 사이의 부분입니다): ||{{{ int  * (@*foo@)(int, int) ;}}}||foo - a pointer to ...|| ||{{{ int  *@( *foo )(int, int)@;}}}||foo - a pointer to a function(int, int) returning ...|| ||{{{ int @* ( *foo )(int, int)@;}}}||foo - a pointer to a function(int, int) returning a pointer to ...|| ||{{{@int  * ( *foo )(int, int)@;}}}||foo - a pointer to a function(int, int) returning a pointer to int.|| 즉 우리말로 읽자면, "foo"는 "int를 가리키는 포인터를 리턴하는 함수 (인자는 두 개의 int)를 가리키는 포인터"라 할 수 있습니다. 흔히 typedef를 써서 위와 같은 함수 포인터를 다른 이름으로 정의합니다: {{{typedef int (*proc_t)(const void *);}}} 이 경우, "typedef"를 빼고 읽으면 됩니다. 즉, ||proc_t||a pointer to function(const void *) returning int.|| 물론 "typedef"를 썼으므로 이는 변수 선언이 아니라, 새로운 타입을 정의한 것이죠. 마지막으로 주의할 것은, 함수 인자에 이름이 있을 경우, 어떤 것이 기준이 되는 이름인지 잘 알고 읽어야 합니다. 예를 들어: {{{int (*proc_t)(int type, const void *data);}}} 여기서 기준이 되는 이름은 "type", "data"가 아닌 "proc_t"입니다. 따라서 proc_t를 해석할 때에는 "type"이나 "data"에 신경쓸 필요는 없습니다. ||proc_t||a pointer to function(int type, const void *data) returning int.|| 끝 - [http://www.cinsk.org 신성국] ---- TODO. 배열 [N]에 대한 예제를 만들 것. TODO. 예제. "{{{int (*ap)[30];}}}", "(*(void(*)())0)();", "void (*(*signal)(int, void (*)(int)))(int);"에 대한 설명을 넣을 것. ---- {{{int (*ap)[30]}}} ||{{{  int   (@*ap@)[30] ;}}}||ap - a pointer to ...|| ||{{{  int  @( *ap )[30]@;}}}||ap - a pointer to {{{array[30]}}} of|| ||{{{ @int   ( *ap )[30]@;}}}||ap - a pointer to {{{array[30]}}} of int|| {{{int *ap[30]}}} (pointer arrays) ||{{{  int   *@ap[30]@ ;}}}||ap - an {{{array[30]}}} of ...|| ||{{{  int   @*ap[30]@ ;}}}||ap - an {{{array[30]}}} of a pointer to ...|| ||{{{  @int   *ap[30]@ ;}}}||ap - an {{{array[30]}}} of a pointer to int|| {{{void (*(*signal)(int,void(*)(int)))(int);}}} ||{{{  void ( * (@*signal@)(int,void(*)(int)) )(int) ;}}}||signal - a pointer to ...|| ||{{{  void ( *@( *signal )(int,void(*)(int))@)(int) ;}}}||signal - a pointer to a function(int,void(*)(int)) returning ...|| ||{{{  void (@* ( *signal )(int,void(*)(int))@)(int) ;}}}||signal - a pointer to a function(int,void(*)(int)) returning a pointer to ... || ||{{{  void@( * ( *signal )(int,void(*)(int)) )(int)@;}}}||signal - a pointer to a function(int,void(*)(int)) returning a pointer to a function(int) returning ... || ||{{{ @void ( * ( *signal )(int,void(*)(int)) )(int)@;}}}||signal - a pointer to a function(int,void(*)(int)) returning a pointer to a function(int) returning void.|| cf. Chapter 5.12 Complicated Declaration from K&R 2nd Ed. * int *f() /* f: function returning pointer to int */ * int (*pf)() /* pf: pointer to function returning int */ * char **argv /* argv: pointer to pointer to char */ * int {{{(*daytab)[13]}}} /* daytab: pointer to {{{array[13]}}} of int */ * int {{{*daytab[13]}}} /* daytab: {{{array[13]}}} of pointer to int */ * void *comp() /* comp: function returning pointer to void */ * void (*comp)() /* comp: pointer to function returning void */ * char (*(*x())[])() /* x: function returning pointer to array[] of pointer to function returning char */ * char (*(*x[3])())[5] /* x: {{{array[3]}}} of pointer to function returning pointer to {{{array[5]}}} of char */ * 내용 추가 {{{[박용범]}}} * 내용 추가 [cheeky]