핵심 정리
공용체
공용체는 union 키워드로 정의하며 멤버 중에서 가장 큰 자료형의 공간을 공유합니다.
// 공용체 정의하기 union 공용체이름 { 자료형 멤버이름; }; // 공용체 변수 선언하기 union 공용체이름 변수이름; // 공용체를 정의하는 동시에 변수 선언하기 union 공용체이름 { 자료형 멤버이름; } 변수; // 공용체를 정의하면서 공용체 별칭 정의하기 typedef union 공용체이름 { 자료형 멤버이름; } 공용체별칭; // 익명 공용체 정의하기 typedef union { 자료형 멤버이름; } 공용체별칭; // 공용체 별칭으로 변수 선언하기 공용체별칭 변수이름;
다음 공용체는 가장 큰 자료형인 int의 공간을 공유하며 공용체의 크기는 int의 크기와 같습니다.
union A { int x; // 가장 큰 자료형인 int의 공간을 공유함 char y; short z; };
공용체 멤버에 접근할 때는 .(점)을 사용합니다.
union 공용체이름 변수이름; 변수.멤버; // 공용체 멤버의 값을 가져옴 변수.멤버 = 값; // 공용체 멤버에 값을 저장
malloc 함수로 공용체 포인터에 메모리를 할당할 수 있으며 이때는 멤버에 접근할 때 -> (화살표 연산자)를 사용합니다.
// 공용체 포인터에 동적 메모리 할당 union 공용체이름 *포인터이름 = malloc(sizeof(union 공용체이름)); // 공용체 별칭으로 포인터를 선언하고 동적 메모리 할당 공용체별칭 *포인터이름 = malloc(sizeof(공용체별칭)); 포인터->멤버; // 공용체 포인터 멤버의 값을 가져옴 포인터->멤버 = 값; // 공용체 포인터 멤버에 값을 저장 free(포인터); // 공용체 메모리 해제
공용체도 포인터에 공용체 변수의 메모리 주소를 구해서 할당할 수 있습니다. 또한, 공용체도 배열 및 배열 포인터로 만들 수 있고, memset, memcpy 함수를 사용할 수 있으며 방식은 구조체와 같습니다.
구조체와 공용체 함께 사용하기
구조체 안에 구조체를 멤버로 넣을 수 있으며 구조체와 공용체는 섞어서 쓸 수 있습니다.
struct 구조체A { 자료형 멤버이름; }; struct 구조체B { 자료형 멤버이름 struct 구조체A 멤버이름; // 구조체A를 멤버로 가짐 }; struct 구조체B 변수이름; 변수.멤버.멤버 // 구조체 안의 구조체 멤버 값을 가져옴 변수.멤버.멤버 = 값; // 구조체 안의 구조체 멤버에 값을 저장
구조체 포인터의 멤버는 -> 연산자로 접근하고, 변수는 .을 사용하여 순차적으로 접근합니다.
struct 구조체B *포인터이름 = malloc(sizeof(struct 구조체B)); 포인터->멤버.멤버; // 구조체 포인터의 구조체에서 멤버 값을 가져옴 포인터->멤버.멤버 = 값; // 구조체 포인터의 구조체에서 멤버에 값을 저장 free(포인터); // 구조체 메모리 해제
구조체는 공용체를 멤버로 가질 수 있습니다.
union 공용체C { 자료형 멤버이름; }; // 구조체와 공용체를 섞어서 사용 struct 구조체C { 자료형 멤버이름; union 공용체C 멤버이름; // 공용체A를 멤버로 가짐 }; 변수.멤버.멤버; // 구조체 안의 공용체 멤버 값을 가져옴 변수.멤버.멤버 = 값; // 구조체 안의 공용체 멤버에 값을 저장
구조체 안에 다른 구조체의 포인터를 멤버로 가지고 있다면 바깥 구조체 포인터에 메모리를 먼저 할당한 뒤 멤버에 메모리를 할당합니다. 메모리를 해제할 때는 반대로 멤버를 먼저 해제한 뒤 바깥 구조체를 해제합니다.
struct 구조체A { 자료형 멤버이름; }; struct 구조체B { 자료형 멤버이름; struct 구조체A *멤버이름; // 구조체A의 포인터를 멤버로 가짐 }; struct 구조체B *포인터이름 = malloc(sizeof(struct 구조체B)); // 바깥 구조체의 포인터에 메모리 할당 포인터->구조체A포인터 = malloc(sizeof(struct 구조체A)); // 멤버 포인터에 메모리 할당 변수->멤버->멤버; // 구조체 포인터의 구조체 포인터에서 멤버 값을 가져옴 변수->멤버->멤버 = 값; // 구조체 포인터의 구조체 포인터에서 멤버에 값을 저장 free(포인터->구조체A포인터); // 구조체 멤버의 메모리를 먼저 해제 free(포인터); // 구조체 메모리 해제
익명 구조체와 익명 공용체를 함께 사용하면 같은 값이지만 이름과 형태를 달리하여 접근할 수 있습니다.
struct 구조체이름 { union { // 익명 공용체 struct { // 익명 구조체 자료형 멤버이름A; // 변수로 접근할 때 사용 자료형 멤버이름B; 자료형 멤버이름C; }; 자료형 배열이름[3]; // 배열로 접근할 때 사용 }; }; struct 구조체이름 변수이름; 변수.멤버A; // 같은 값을 변수로 접근 변수.배열[0]; // 같은 값을 배열의 인덱스로 접근