C의 선언

typedef

3.1) typedef

typedef 키워드는 형식을 정의하는 데 사용된다다음은 typedef를 사용하는 예제이다.

02_typedef.cpp

#include <iostream>

using namespace std;

int sum(int a, int b) { return a + b; }

int mul(int a, int b) { return a * b; }

int main(void) {

// Data를 int 형식으로 정의한다

typedef int Data;

Data data = 10;

cout << "변수: " << data << endl;

// DataPtr를 Data에 대한 포인터 형식으로 정의한다

typedef Data *DataPtr;

DataPtr data_ptr = &data;

cout << "포인터: " << *data_ptr << endl;

// DataArr를 크기 3인 Data 변수의 배열 형식으로 정의한다

typedef Data DataArr[5];

DataArr data_arr = { 1, 2, 3 };

cout << "배열: ";

for (int i = 0; i < 3; ++i) cout << data_arr[i] << ' ';

cout << endl;

// FuncPtr를 (int, int)과 같이 인자를 받고

// int형 값을 반환하는 함수에 대한 포인터 형식으로 정의한다

typedef int(*FuncPtr)(int, int);

FuncPtr fp = sum;

cout << "fp(3, 5): " << fp(3, 5) << endl;

fp = mul;

cout << "fp(3, 5): " << fp(3, 5) << endl;

return 0;

}

typedef 키워드를 함수 내부에서 사용할 수 있다는 사실에서부터 놀랐을 수도 있다이후에도 설명할 것이지만 사실 typedef 키워드는 extern 키워드와 같은 선언의 요소이며 typedef로 정의된 문장 또한 선언의 일종이다. typedef 뒤에는 반드시 선언이 따라온다후에 복잡한 선언을 분석하면서 이에 대해 논의할 것이다참고로 위 예제는 C++ 언어로 작성되었지만, C언어에서도 이 내용은 성립하며방금 말했듯 typedef로 작성된 문장은 선언문이므로 함수 내부에서 사용할 때 코드 중간에 넣으면 컴파일 시에 오류가 발생한다(C에서 선언은 반드시 함수의 위 부분에 있어야 한다).

typedef가 무엇인지 알고 있으니, typedef를 이용해 다음 문장들을 선언해보라반드시 한 문장에 정리할 필요는 없고여러 개의 typedef 문장을 사용해도 좋다.

- integer는 int 형식의 변수입니다.

- character는 char 형식의 변수입니다.

- intPtr는 int형 변수에 대한 포인터 변수입니다.

- intArr는 크기가 5인 int형 변수의 배열입니다.

- intFuncIntCharInt는 (int, char, int) 형식으로 인자를 받고 int형 값을 반환하는 함수입니다.

답은 다음과 같다.

int integer;

char character;

int *intPtr;

int intArr[5];

int intFuncIntCharInt(int, char, int);

이 문제는 너무 쉽다고 느꼈을 수 있다그렇다면 다음을 해결해보라당연히 typedef를 이용한다.

- intArrArr는 ((int형 변수 3개의 배열) 2개의 배열)입니다.

- intPtrArr는 ((int형 변수에 대한 포인터 변수) 5개의 배열)입니다.

- intArrPtr는 ((int형 변수 4개의 배열)에 대한 포인터 변수)입니다.

- intFuncComp는 ((((int, int) 형식으로 인자를 받고 int형 값을 반환하는 함수)에 대한 포인터)를 인자로 받고 int형 값을 반환하는 함수)입니다.

답은 다음과 같다.

typedef int intArr3[3];

intArr3 intArrArr[2];

typedef int *intPtr;

intPtr intPtrArr[5];

typedef int intArr4[4];

intArr4 *intArrPtr;

typedef int (*Comp)(int, int);

int intFuncComp(Comp comp);

이 문제도 해결했다면 더 복잡한 다음 문제를 보자.

- qsort는 다음과 같은 함수입니다.

반환형값을 반환하지 않습니다.

첫 번째 인자 base는 void형 포인터 변수입니다.

두 번째 인자 nelem은 unsigned형 변수입니다.

세 번째 인자 width는 unsigned형 변수입니다.

네 번째 인자 fcmp는 다음과 같은 함수에 대한 포인터 변수입니다.

>> 반환형: int형 값입니다.

>> 첫 번째 인자와 두 번째 인자는 모두 const void형 포인터 변수입니다.

- signal은 다음과 같은 함수입니다.

반환형: int형 변수를 인자로 받고 void형 포인터 값을 반환하는 함수에 대한 포인터입니다.

첫 번째 인자 signal_number은 int형 변수입니다.

두 번째 인자 signal_handler는 int형 변수를 인자로 받고 void형 포인터 값을 반환하는 함수에 대한 포인터입니다.

답은 다음과 같다.

typedef const void *CVP;

typedef int Compare(CVP, CVP);

void qsort(void *base, unsigned nelem, unsigned width, Compare fcmp);

typedef void (*SignalHandler)(int);

SignalHandler signal(int signal_number, SignalHandler signal_handler);

사실 이렇게 끔찍한 코드가 필요한 일은 거의 없지만이해하는 것은 필요하다무엇보다 컴파일러를 만들려는 우리인 만큼 선언이 어떤 의미를 가지고 있는지는 명확하게 이해하고 있는 것이 이치에 맞다.

그런데 사실 typedef는 선언을 위해 반드시 필요한 키워드는 아니다. typedef를 이용한 선언은 typedef 키워드가 없이도 얼마든지 가능하다즉 우리는 위 예제에서 모든 typedef 키워드를 없애고도 제시하는 선언을 만들어낼 수 있다그것이 어떻게 가능할까물론 signal도 가능한데이는 어떻게 선언해야 하는가?

댓글

댓글 본문
graphittie 자세히 보기