typedef
typedef를 배우기 전에 다음의 코드를 살펴보자.
<소스코드>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
#include <stdio.h>
struct point {
int xpos;
int ypos;
};
int main(void) {
struct point pnt = { 2, 3 };
printf("[%d, %d]", pnt.xpos, pnt.ypos);
return 0;
}
|
cs |
9번 라인을 보면 struct point형 변수를 선언하기 위해 struct point pnt = {2, 3}; 으로 선언한 것을 볼 수 있다. 매번 struct를 사용하는 것은 불편하다. 그렇다면 int num = 10; 처럼 간단하게 할 수 있는 방법이 없을까? 있다. 바로 typedef를 사용하면 된다. 이를 다음의 소스코드와 이전의 소스코드를 비교하며 이해해보자.
<소스코드>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
#include <stdio.h>
typedef struct {
int xpos;
int ypos;
} Point;
int main(void) {
Point pnt = { 2, 3 };
printf("[%d, %d]", pnt.xpos, pnt.ypos);
return 0;
}
|
cs |
두 코드의 실행결과는 모두 동일하며 3번 라인을 보면 struct 앞에 typedef 키워드가 있고 point라는 구조체 이름이 빠지고 구조체의 마지막에 Point라고 붙여진것을 볼 수 있다. 이를 통해 9번 라인에서 볼 수 있듯이 단순하게 Point pnt = {2, 3}; 으로 구조체 변수를 간단하게 생성하는 것을 볼 수 있다.
함수로의 구조체 변수 전달과 반환
기본 자료형과 마찬가지로 구조체 변수 역시 매개변수에 복사가 되거나 반환될 수 있다. 다음의 코드를 살펴보자.
<소스코드>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
typedef struct {
int xpos;
int ypos;
} Point;
void showPosition(Point pnt) {
printf("[%d, %d] \n", pnt.xpos, pnt.ypos);
}
Point GetCurrentPosition(void) {
Point cen;
printf("pos를 입력하시오 : ");
scanf("%d %d", &cen.xpos, &cen.ypos);
return cen;
}
int main(void) {
Point curPos = GetCurrentPosition();
showPosition(curPos);
return 0;
}
|
cs |
<실행결과>
라인 9번에서 볼 수 있듯이 매개변수로 구조체 변수가 들어갔고 21번 라인에서 볼 수 있듯 반환값을 Point 변수 curpos에 대입하는것을 볼 수 있다. 또한 매개변수로 구조체의 포인터 변수도 들어갈 수 있다. 이를 통해 Call by reference도 할 수 있다. 이를 예시 코드를 통해 알아보자.
<소스코드>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
typedef struct {
int xpos;
int ypos;
} Point;
void OrgSynTrans(Point* pnt) {
pnt->xpos = pnt->xpos * -1;
pnt->ypos = pnt->ypos * -1;
}
void showPosition(Point pnt) {
printf("[%d, %d] \n", pnt.xpos, pnt.ypos);
}
int main(void) {
Point pos = { 7, -5 };
OrgSynTrans(&pos);
showPosition(pos);
OrgSynTrans(&pos);
showPosition(pos);
return 0;
}
|
cs |
<실행결과>
9번 라인에서 볼 수 있듯이 함수의 매개변수로 구조체의 주소값을 넘겨서 원점 대칭하는것을 알 수 있다. 따라서 메인함수의 좌표값을 메인함수 외부에서 변경하는것을 볼 수 있다.
또한 구조체 변수 역시 구조체의 멤버로 포함될 수 있다. 이를 구조체의 중첩이라 한다. 다음의 소스코드를 확인하자.
<소스코드>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
typedef struct {
int xpos;
int ypos;
} Point;
typedef struct {
Point cen;
double rad;
} Circle;
void showCircleInfo(Circle * c) {
printf("[%d, %d] \n", (c->cen).xpos, (c->cen).ypos);
printf("radius: %g \n\n", c->rad);
}
int main(void) {
Circle c1 = { {1, 2}, 3.5 }; // 구조체가 중첩 됨
showCircleInfo(&c1);
return 0;
}
|
cs |
<실행결과>
20번 라인에서 볼 수 있듯이 구조체가 중첩된 것을 알 수 있다.
UNION
구조체와 공용체(union)의 차이
typedef struct {
int mem1;
int mem2;
double mem3;
} Sbox;
typedef union {
int mem1;
int mem2;
double mem3;
} Ubox;
위의 Sbox, Ubox의 sizeof 연산을 해보면 각각 16 byte, 8 byte 인것을 확인할 수 있다. 이를 그림으로 표현하면 다음과 같다.
이 union은 하나의 메모리 공간에 둘 이상의 방식으로 접근할 수 있다는 특성이 있다.
Enum 열거형
enum을 설명하기 전에 먼저 다음의 소스코드를 보자.
<소스코드>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
|
#include <stdio.h>
typedef enum {
Do = 1, Re = 2, Mi = 3, Fa = 4, Sol = 5, La = 6, Ti = 7
} Syllable;
void Sound(Syllable sy) {
switch (sy) {
case Do:
puts("도 입니다.");
return;
case Re:
puts("레 입니다.");
return;
case Mi:
puts("미 입니다.");
return;
case Fa:
puts("파 입니다");
return;
case Sol:
puts("솔 입니다.");
return;
case La:
puts("라 입니다.");
return;
case Ti:
puts("시 입니다.");
return;
}
}
int main(void) {
Syllable tone;
for (tone = Do; tone <= Ti; tone++)
Sound(tone);
return 0;
}
|
cs |
<실행결과>
열거형은 연관이 있는 이름을 동시에 상수로 선언할 수 있다는 장점이 존재한다.
이 포스팅은 윤성우님의 열혈 C를 기반으로 작성되었습니다.
'C' 카테고리의 다른 글
14. 메모리 및 동적할당 (0) | 2021.06.28 |
---|---|
11. 구조체와 사용자 정의 자료형 (0) | 2021.06.27 |
10. 문자열 관련 함수 (0) | 2021.06.27 |
9. 함수 포인터 & void 포인터 (0) | 2021.06.26 |
8. 2차원 배열과 포인터 (0) | 2021.06.26 |