서론

최근에 여러 개념들을 공부하면서 글로 정리할 필요성을 다시 느끼게 되었다. 그래서 워밍업? 같은 것을 하려고 이 글을 쓰게 되었다.

C에서의 변수 선언과 type

이 글에서는 C에서 변수 선언을 할때 내가 원하는 타입을 어떻게 지정할 수 있을지에 대해 다룰 것이다. 원하는 타입을 지정하기 위해서는 C에서의 타입 지정 규칙을 알아야 한다.

C에서의 타입 지정 규칙은 연산자 우선순위를 따른다. 이것이 무슨 말인 것이냐. 연산자 우선순위가 높은 것부터 해석된다는 것이다.

일단 각 연산자는 다음과 같이 해석된다. 여기서 ~는 다음으로 해석될 연산자이다.

  • *: ~를 가리키는 포인터
  • [N]: 원소가 ~인 길이 N의 배열
  • (): ~를 반환하는 함수

예를 들어보자. 일단 type name(int, float 같은거)도 하나의 전위 연산자라고 가정하자. 그리고 일반적으로 전위연산자가 가지는 우선순위를 갖는다고 가정하자. 자세한 것은 여기를 보면 알 수 있다.

int a;
 1

a를 피연산자라고 하면 a에 적용되는 연산자는 int 하나이다. 연산자가 하나이므로 연산자 우선순위를 따질것이 없다. 따라서 변수 a는 그냥 타입이 int인 것이다.

이번엔 *(포인터)를 붙여보자. 포인터는 무언가를 가리키는 것이다.

int *a;
 2  1

이번엔 연사자가 두개(int, *)있다. 어떤 연산자가 우선순위가 더 높을까? 둘다 전위연산자이므로 a에 더 가까이 있는 *가 우선순위가 더 높다는 것을 알 수 있다. 따라서 *먼저 해석된다. 따라서 일단 a~를 가리키는 포인터이다. 이제 ~가 뭔지를 해석해야 하므로 * 다음으로 우선순위를 가지는 int를 해석한다. int는 그냥 type name이니까 해석하면 그냥 int이다. ~를 가리키는 포인터~int를 넣으면 int를 가리키는 포인터가 된다. 따라서 aint를 가리키는 포인터이다.

다음! 간단히 설명하겠다.

int *a[3];
 3  2  1

가장 우선순위가 높은 것은 [3]이다. 따라서 a는 일단 ~를 원소로 가지는 길이 3의 배열이다. 그럼 무엇(~)을 원소로 가질까? 다음으로 우선순위가 높은 것은 *이므로 (~를 가리키는 포인터)를 원소로 가지는 길이 3의 배열이 된다. *다음으로 우선순위가 높은 것은 int이다. 따라서 int를 가리키는 포인터를 원소로 가지는 길이 3의 배열a인 것이다.

다음!! 더더 간단히!!!

int (*a)[5];
 3   1   2

우선순위가 높은 순서대로 나열한다.

  1. *: ~를 가리키는 포인터. 괄호 때문에 *의 우선순위가 더 높다.
  2. [5]: ~를 원소로 가지는 길이 5의 배열을 가리키는 포인터.
  3. int: int를 원소로 가지는 길이 5의 배열을 가리키는 포인터.

다음… 참으로 길다.

int (*(*(*a)[4])(float, long))[1];
 7   5 3 1   2        4        6
  1. *: ~를 가리키는 포인터.
  2. [4]: ~를 원소로 가지는 길이 4의 배열을 가리키는 포인터.
  3. *: ~를 가리키는 포인터를 원소로 가지는 길이 4의 배열을 가리키는 포인터.
  4. (float, long): ~를 반환하는 함수를 가리키는 포인터를 원소로 가지는 길이 4의 배열을 가리키는 포인터.
  5. *: ~를 카리키는 포인터를 반환하는 함수를 가리키는 포인터를 원소로 가지는 길이 4의 배열을 가리키는 포인터.
  6. [1]: ~를 원소로 가지는 길이 1의 배열을 카리키는 포인터를 반환하는 함수를 가리키는 포인터를 원소로 가지는 길이 4의 배열을 가리키는 포인터.
  7. int: int를 원소로 가지는 길이 1의 배열을 카리키는 포인터를 반환하는 함수를 가리키는 포인터를 원소로 가지는 길이 4의 배열을 가리키는 포인터.