서론
아마 c언어를 배웠던 사람이라도 이 union은 모르는 사람이 많을 것 같다. 내가 그랬고 내 주변도 그랬다. 그런데 임베디드를 개발하면서 남들이 작성한 코드에 union이 있었고 코드 분석을 위해서 알아야 했다. 그리고 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 }
구조체는 가장 큰 변수를 기준으로 메모리를 할당한다. 따라서 위 sizeTest_struct는 double이 8바이트, int도 double을 따라서 8바이트로 할당되어 총사이즈는 16바이트가 출력된다. 그러나 sizeTest_union은 가장 큰 변수인 b가 double이므로 8바이트를 모든 변수가 공유하게 되어 총 사이즈는 8바이트가 출력된다. 변수들이 메모리를 공유하는건 변수들에 값을 넣어보면 바로 확인이 가능하다. 아래와 같이 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 }
다시 b에 20을 쓰면 a와 b 모두 20을 출력함을 볼 수 있다.
#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 }
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을 접할 수 있다.
그러나 최근에는 임베디드통신에서도 여러 플랫폼과의 호환을 위해서 이더넷, REST, JSON과 같은 키워드가 점점 늘어나는걸 체감하고있다.