공용체
구조체는 struct라는 키워드를 사용하는 반면, 공용체는 union이라는 키워드를 사용해서 정의한다.
ex)
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 | #include<stdio.h> typedef struct { int mem1; int mem2; double mem3; }SBox; typedef union { int mem1; int mem2; double mem3; }UBox; int main() { SBox sbx; UBox ubx; printf("%p %p %p \n", &sbx.mem1, &sbx.mem2, &sbx.mem3); printf("%p %p %p \n", &ubx.mem1, &ubx.mem2, &ubx.mem3); printf("%d %d \n", sizeof(SBox), sizeof(UBox)); return 0; } |
0x7ffeefbff5a8 0x7ffeefbff5ac 0x7ffeefbff5b0
0x7ffeefbff5a0 0x7ffeefbff5a0 0x7ffeefbff5a0
16 8
가장 주목해서 봐야할 부분은 UBox형 변수를 구성하는 멤버 mem1, mem2, mem3의 주소 값이 동일하다는 사실이다.
그리고 다음과 같은 할당특성의 결과이다.
구조체는 구조체를 구성하는 멤버가 각각 할당이 된다고 한다면, 공용체는 변수가 선언되면 공용체를 구성하는 멤버는 각각 할당되지 않고, 그 중 크기가 가장 큰 멤버의 변수만 하나 할당되어 이를 공유하게 된다.
ex)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | #include<stdio.h> typedef union { int mem1; int mem2; double mem3; }UBox; int main() { UBox ubx; ubx.mem1=20; printf("%d \n",ubx.mem2); ubx.mem3=7.15; printf("%d \n", ubx.mem1); printf("%d \n", ubx.mem2); printf("%lf \n", ubx.mem3); return 0; } |
출력결과
20
-1717986918
-1717986918
7.15
13행 : 상위 4바이트의 메모리 공간에 20을 저장한다.
14행 : mem2는 int형 변수이므로 이 이름에서 접근할 경우 상위 4바이트의 메모리 공간을 참조하게 된다. 앞 서 13행에서 이 공간에 20을 저장했으므로 20이 출력된다.
17, 18행 : 16행에서 실수를 저장하면서 덮어써버렸기 때문에, 상위 4바이트를 읽어서 출력하면 알 수 없는 값이 출력된다.
공용체의 유용함
' 하나의 메모리 공간을 둘 이상의 방식으로 접근할 수 있다'라는 것이다. 하지만 필자는 아직 잘 모르겠다.
예시를 하나 들어보자
int형 정수를 하나 입력받고, 입력받은 정수의 상위 2바이트와 하위 2바이트 값을 양의 정수로 출력한다. 그 후, 상위 1바이트와 하위 1바이트에 저장된 값의 아스키 문자를 출력해보라
ex)
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 | #include<stdio.h> typedef struct { unsigned short upper; unsigned short lower; }DBShort; typedef union { int mem1; char mem2[4]; DBShort sBuf; }RDBuf; int main() { RDBuf buf; printf("정수입력: "); scanf("%d", &buf.mem1); printf("상위 2바이트 : %u \n", buf.sBuf.upper); printf("하위 2바이트 : %u \n", buf.sBuf.lower); printf("상위 1바이트 아스키코드 : %c \n", buf.mem2[0]); printf("하위 1바이트 아스키코드 : %c \n", buf.mem2[3]); return 0; } |
정수입력: 1145258561
상위 2바이트 : 16961
하위 2바이트 : 17475
상위 1바이트 아스키코드 : A
하위 1바이트 아스키코드 : D
3행에서 두 개의 unsigned short형 변수를 멤버로 지니는 4바이트 크기의 구조체를 정의
9행 : 모든 멤버의 크기가 4바이트이므로 4바이트가 할당
13행 : 공용체의 멤버로 구조체 변수 선언
20행 : 18행에 선언된 4바이트 크기의 공용체 변수에 정수를 입력받고 있다. iBuf라는 이름의 int형으로 선언된 멤버를 이용해서 입력 받고 있다.
22, 23 행 : 상위 2바이트와 하위 2바이트 값을 각각 양의 정수형태로 출력하고 있다.
24, 25 행 : 상위 1바이트와 하위 1바이트의 값을 각각 아스키 코드 문자로 출력하고 있다.
공용체는 이런 식으로 많이 쓰이기 때문에 이 예제를 기억해두면 나중에 쓸모가 있을 것이다.
열거형
열거형의 정의와 변수의 선언
열거형으로 syllable이라는 이름의 자료형을 정의한다는 것은 syllable형 변수에 저장이 가능한 정수 값들을 결정하겠다. 라는 의미를 지닌다.
구조체와 공용체는 멤버에 저장할 값의 유형을 결정하였다면 열거형에는 저장이 가능한 값 자체를 정수의 형태로 결정한다.
열거형의 정의
enum syllable
{
Do=1, Re=2, Mi=3, Fa=4, So=5, La=6, Ti=7
};
Do= 1 // Do를 정수 1을 의미하는 상수로 정의한다. 그리고 이 값은 syllable형 변수에 저장이 가능하다.
즉 위의 열거형 정의에서는 Do, Re, Mi, Fa, So, La, Ti 라는 이름의 상수를 각각 1,2,3,4,5,6,7로 정의하고, 이 값들을 syllable형 변수가 저장할 수 있는 값들로 제한한 것이다.
ex)
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 | #include<stdio.h> typedef enum syllable { Do=1, Re=2, Mi=3, Fa=4, So=5, Ra=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 So: puts("솔은 작은 솔방울"); return; case Ra: puts("라는 라디오고요~"); return; case Ti: puts("시는 졸졸 시냇물"); return; } } int main() { Syllable tone; for(tone=Do;tone <= Ti; tone+=1) Sound(tone); return 0; } |
도는 하얀 도라지
레는 둥근 레코드
미는 파란 미나리
파는 예쁜 파랑새
솔은 작은 솔방울
라는 라디오고요~
시는 졸졸 시냇물
위 예제의 Do, Re ... 를 대신해서 1, 2 ... 를 사용해도 결과는 같다. 그 이유는 열거형 상수들은 int형으로 표현되는 상수이기 때문에
열거형을 정의하는데 있어 상수의 값을 명시하지 않으면, 0부터 시작해서 1씩 증가하는 형태로 결정이 된다.
enum color {RED, BLUE, WHITE, BLACK};
0 1 2 3
열거형의 유용함은 이름있는 상수의 정의를 통한 의미의 부여에 있다.
연관있는 이름을 동시에 상수로 선언할 수 있다. 둘 이상의 연관이 있는 이름을 상수로 선언함으로써 프로그램의 가독성을 높이는데 있다.
실제로 변수의 선언이 아닌 상황에서는 아래와 같이 정의하기도 한다.
enum
{
Do = 1,
Re = 2,
Mi = 3,
. . . .
}
이와같이 정의가 되어도 열거형 상수 Do,Re,Mi . . . .는 상수로써 의미를 지닌다.
'programming > C' 카테고리의 다른 글
C // 메모리 관리, 메모리의 동적할당 (0) | 2018.01.05 |
---|---|
C // 파일 입출력 (0) | 2018.01.04 |
C // 구조체와 사용자 정의 자료형2 (0) | 2017.12.30 |
C // 구조체와 사용자 정의 자료형 1 (0) | 2017.12.29 |
C // 문자와 문자열관련함수 (0) | 2017.12.28 |