구조체와 정의 방법은 같으나 멤버를 저장하는 방식이 다름
구조체는 멤버들이 각각 공간을 차지하지만 공용체는 모든 멤버가 가장 큰 자료형의 공간을 공유
union 공용체이름 {
자료형 멤버이름;
};
/*------------------------------*/
union Box {
short a; // 2바이트
float b; // 4바이트
char c[8] // 8바이트
};
union Box b1; // 공용체 변수 선언
printf("%d", sizeof(b1)); // 8 출력, 공용체의 전체 크기는 가장 큰 자료형의 크기
union Box {
short a; // 2바이트
float b; // 4바이트
char c[8] // 8바이트
};
union Box *b1 = malloc(sizeof(union Box));
strcpy(b1->c, "what");
free(b1);
struct Phone {
int areacode;
unsigned long long number;
};
struct Person {
char name[20];
int age;
struct Phon phone;
}
struct Person p1;
p1.phone.areacode = 82; // 변수.멤버.멤버로 접근
구조체 안에 구조체 정의도 가능, 하지만 정의한 뒤 반드시 변수 선언을 해야함
struct Person {
char name[20];
int age;
struct Phone {
int areacode;
unsigned long long number;
} phone;
};
변수 선언과 동시에 초기화도 가능
struct Person p1 = { .name = "A", .age = 20, { .areacode = 82, .number = 123123} };
struct Person p2 = { "B", 20, { 82, 234234} };
메모리 할당도 가능
struct Person *p1 = malloc(sizeof(struct Person));
p1->phone.areacode = 82; // 포인터->멤버.멤버로 접근
free(p1);
enum 열거형이름 {
값1 = 초깃값,
값2,
값3
};
enum 열거형이름 변수이름;
/*--------------------------------------*/
enum Week {
Sunday = 0,
Monday,
Tuesday,
Wednesday,
Thursday,
Friday,
Saturday
};
enum Week week;
week = Tuesday;
printf("%d", week); // 2 출력
열거형도 typedef로 별칭 정의 가능
enum count {
First = 1,
Second,
Third
};
enum count c1;
c1 = First;
switch (c1)
{
case First:
printf("First");
break;
case Second:
printf("Second");
break;
case Third:
printf("Third");
break;
default:
break;
}
(자료형)변수
(자료형)값
/*----------------------*/
int n1 = 32;
int num2 = 7;
float num3;
num3 = (float)num1 / num2;
(자료형 *)포인터
*(자료형 *)포인터 // 포인터를 변환하면서 역참조
/*--------------*/
int *numPtr = malloc(sizeof(int));
char *cPtr;
*numPtr = 0x12345678;
cPtr = (char *)numPtr;
printf("%x", *cPtr); // 78 출력, 낮은 자릿수 1바이트를 가져옴
free(numPtr);
*(자료형 *)void 포인터
/*--------------------------------*/
int n1 = 10;
void *ptr;
ptr = &n1;
printf("%d", *(int *)ptr); // 10 출력, void 포인터를 int 포인터로 변환하고 역참조, void 포인터는 역참조할 수 없기 때문
(struct 구조체이름 *)포인터
((struct 구조체이름 *)포인터)->멤버
/*-------------------------------------------*/
struct Data {
char c1;
};
struct Data *d1 = malloc(sizeof(struct Data));
void *ptr;
d1->c1 = 'a';
ptr = d1;
printf("%c", ((struct Data *)ptr)->c1); // a 출력
free(d1);
포인터 변수에 +, -, ++, --를 사용, *나 / 연산자와 실수는 사용 불가
포인터 + 값
포이터 - 값
/*-----------------------*/
int numArr[5] = {1, 2, 3, 4, 5};
int *numPtrA;
numPtrA = numArr;
printf("%p %p %p", numPtrA, numPtrA + 1, numPtrA + 2); // 메모리주소, 메모리주소 + 4, 메모리주소 + 8 출력, +1을 할 때마다 int형의 크기인 4바이트씩 증가
printf("%d %d", *numPtrA, *(numPtrA + 1)); // 1 2 출력, *(numPtrA + 1) == numArr[1]
void 포인터는 자료형의 크기가 정해져 있지 않아 연산을 해도 얼마나 이동할지 알 수 없어 포인터 연산을 할 수 없다.
(자료형 *)void포인터 + 값
/*-------------------*/
(int *)void v1 + 1
(포인터 + 값)->멤버
/*-----------------------------------*/
struct Data {
int n1;
int n2;
};
struct Data d[3] = { { 1, 2 }, { 3, 4 }, { 5, 6 } };
struct Data *ptr;
ptr = d;
printf("%d", (ptr + 1)->n1); // 3 출력, d[1].n1과 같음
printf("%d", (ptr + 2)->n2); // 6 출력, d[2].n2와 같음
포인터 연산을 하면 구조체 크기만큼 더하고 뺌
void 포인터로도 가능
((struct 구조체이름 *)포인터 + 값)->멤버
/*-----------------------------------*/
void *ptr = malloc(sizeof(struct Data) * 3);
((struct Data *)ptr)->n1 = 10;
free(ptr);