http://www.tcpschool.com/cpp/cpp_struct_unionEnum
https://bite-sized-learning.tistory.com/315
코드를 분석하는 중에 class 안에 union 이 있는 이런 코드를 보게 되었다.
class A
{
protected:
union
{
struct
{
WORD wMin:6;
WORD wHour:5;
...
}
}
}
union이 뭐지??
union
union은 struct와 유사하지만 union의 변수 중 가장 큰 변수의 메모리를 모든 변수가 공유한다는 점에서 다르다.
같은 변수를 가지는 struct와 union의 size를 출력해보면 아래와 같이 결과가 다른것을 확인할 수 있다.
typedef struct sizeTest_struct
{
int a; // 4byte
double b; // 8byte
}sizeTest_struct;
typedef union sizeTest_union
{
int a;
double b;
}sizeTest_union;
int main()
{
sizeTest_struct s;
sizeTest_union u;
printf("struct size : %d\r\n", sizeof(s)); // 16
printf("union size : %d\r\n", sizeof(u)); // 8
}
구조체(Struct) 는 가장 큰 변수를 기준으로 메모리를 할당한다.
따라서 위 sizeTest_struct는 double이 8바이트, int도 double을 따라서 8바이트로 할당되어 총사이즈는 16바이트가 출력된다.
그러나 sizeTest_union은 가장 큰 변수인 b가 double이므로 8바이트를 모든 변수가 공유하게 되어 총 사이즈는 8바이트가 출력된다.
구조체 주소 할당 Rule
자세히 >>
참고로 Struct 는 가장 큰 변수의 타입 크기의 배수만큼 메모리를 잡는다.
예를 들면
struct Packet00{
char flags; // 1byte
short count; // 2byte
int msg; // 4byte
}
sizeof(Packet00);
결과는 7byte 가 아니라 8byte 가 나오게 된다.

또 한 가지, 가장 큰 바이트 의 배수로 메모리 주소를 정한다.
아래 글에 설명이 좋으니 참고하면 된다.
https://dobby-the-house-elf.tistory.com/358
[C++] 구조체의 크기 (size of struct)
구조체의 크기는 구조체를 구성하는 요소들에 의해 정해 집니다. 하지만 크기를 출력해보면 예상한 값과 다르게 나올때가 있는데, 그 이유와 구조체의 구조에 대해 알아보겠습니다. struct Packet00
dobby-the-house-elf.tistory.com
union 의 변수들이 메모리를 공유하는건 변수들에 값을 넣어보면 바로 확인이 가능하다.
아래와 같이 union의 변수 a와 b에 0을 쓰면 둘 다 0이 출력됨을 볼 수 있다.
#include <stdio.h>
typedef union test_union
{
int a;
int b;
}test_union;
int main()
{
test_union u = {0, 0};
printf("u.a : %d, u.b : %d\r\n", u.a, u.b); // u.a : 0, u.b : 0
}
그리고 a에 10을 쓰면 a는 물론 b도 10을 출력이 되는걸 볼 수 있다.
#include <stdio.h>
typedef union test_union
{
int a;
int b;
}test_union;
int main()
{
test_union u = {0, 0};
printf("u.a : %d, u.b : %d\r\n", u.a, u.b); // u.a : 0, u.b : 0
u.a = 10;
printf("u.a : %d, u.b : %d\r\n", u.a, u.b); // u.a : 10, u.b : 10
u.b = 20;
printf("u.a : %d, u.b : %d\r\n", u.a, u.b); // u.a : 20, u.b : 20
}
다시 b에 20을 쓰면 a와 b 모두 20을 출력함을 볼 수 있다.
그렇다면 왜 Union 을 쓸 까?
아래의 코드를 보면 union 을 쓰는 이유를 유추 할 수 있다.
union ShareData
{
unsigned char a;
unsigned short b;
unsigned int c;
};
int main(void)
{
ShareData var;
var.c = 0x12345678;
cout << hex;
cout << var.a << endl;
cout << var.b << endl;
cout << var.c;
return 0;
}
shareData 라는 union 타입은 가장 큰 멤버 변수가 unsigned int 이다.
그렇기 때문에 4byte 인 unsigned int 형의 데이터만큼 메모리 공간이 잡히고 모든 변수들이 그 한 공간을 공유한다.
main 함수에서 var.c = 0x12345678 (4byte) 를 대입했다.
이때 var.c 를 출력하면 (16진수로) 12345678 이 나오는것은 당연하니 Pass
var.b 는 unsigned short 즉 2byte 자료형 이다. 12345678 에서 2byte 가 짤린 5678을 var.b 가 볼 수 있는 것이다.
var.c 는 unsigned char 즉 1byte 자료형 이다. 0x78 을 볼 수 있고, 0x78은 십진수로 120, 120은 char 로 문자 ' x ' 이다.
공용체에 저장된 값의 의미는 값을 저장할 때 공용체의 어떤 멤버 변수를 사용했는지에 따라 달리 해석된다.
따라서 공용체가 어떤 멤버 변수를 사용하여 저장했는지를 별도의 변수로 저장하든가 하여, 사용할 때에도 같은 멤버 변수를 사용해야 한다.
union 활용
union은 변수들이 메모리를 공유한다는 특징 때문에 통신에서 아주 편리하게 이용된다.
typedef union comm
{
char buffer[4];
struct {
char version;
char header;
char length;
char address;
}segment;
}comm;
int main()
{
MessageSend(comm.buffer[0]);
MessageReceive(comm.segment.version, comm.segment.header, comm.segment.length, comm.segment.address);
}
통신을 위해서는 데이터를 주고받아야 한다. 그리고 데이터는 패킷 단위로 묶어서 보내게 되는데, 단순히 보내는 건 쉽지만 받는 입장에서는 덩어리로 온 데이터를 받아서 분해하고 다시 묶어서 보내기가 여간 까다롭다. 정확히는 까다롭다기보다는 귀찮다. 그런데 위와 같이 공용체를 사용한다면 보낼 때는 buffer로 한 번에 보내고 받을 때는 struct의 변수들로 각각 받을 수 있어서 편리하다. 이때문에 통신에서 union을 접할 수 있다.
union 타입 comm 에 제일 큰 타입은 동일하게 char 4개인 4byte 다
다시 말해 buffer 는 segment 와 정확하게 메모리를 공유하고 있다.
그래서 보낼때는 buffer 로 보내고 받을 때는 , segment.version 처럼 항목으로 받을 수 있는 것이다.
또,
한가지 아래와 같이 비트필드를 지정하여
( cf 비트 필드 참고 https://forward-movement.tistory.com/254 )
이런 식으로 union 에 u-char 타입인 val 와 u-char 타입 8개가 있는 struct bits 를 넣어
bitflags_t 는 총 1byte 가 되고 구조체인 bits 와 unsigned char 타입인 var 는 같은 메모리를 1byte 를 공유하게 된다.
그렇기 때문에 어떻게 union에 접근하냐에 따라서 통째로 읽을지 비트 단위로 읽을지 달라진다.
'Language & etc > C++ Keyword' 카테고리의 다른 글
#name (0) | 2022.07.08 |
---|---|
Inline (0) | 2022.05.13 |