struct 구조체명 {
자료형 멤버명;
}
구조체의 기본 구조
---------------------------------------------------------------------------------------------
struct data {
char a;
int b;
}:
---------------------------------------------------------------------------------------------
구조체를 선언함과 동시에 변수 선언
struct data {
char a;
int b;
}: data_type_1; data_type_2;
---------------------------------------------------------------------------------------------
구조체 타입 data를 정의한 뒤에 data_type_1과 data_Type_2 선언
struct data {
char a;
int b;
}:
struct data data_type_1;
struct data data_type_2;
---------------------------------------------------------------------------------------------
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 | #include <stdio.h> struct data { char a; int b; }; int main() { struct data data_type_var; printf("char : %lu Byte\n", (unsigned long)sizeof(char)); printf("int : %lu Byte\n", (unsigned long)sizeof(int)); printf("struct data : %lu Byte\n",(unsigned long)sizeof(struct data)); data_type_var.a = 'A'; data_type_var.b = 100; printf("data_type_var.a : %c\n",data_type_var.a); printf("data_tyoe_var.b : %d\n",data_type_var.b); return 0; } | cs |
struct 에서는 char를 4byte로 처리하기 때문에 struct data에서 4+4 = 8이 나오게된다.
소스 코드를 컴파일할 때 해당 구조체의 크기를 정렬하여 컴파일하기 떄문이다
이를 구조체 멤버정렬(struct member alignment) 라고 한다 .
소스 코드를 컴파일 할 때 구조체 멤버 정렬이 발생하는 이유는 CPU에서 메모리에 접근 할 때 특정한 사이즈로 접근을 해야 더욱 속도가 빠르기 때문이다.
멤버 정렬을 하면서 정렬 사이즈 단위에 부족하면 부족한 해당 바이트 값만큼 패딩을 추가하여 정렬 사이즈를 맞춘다 ( 패딩 = 남은 공간을 채우는것)
( %lu = unsigned long 이라는 의미이며 ul로 쓰면 에러가 발생할 수 있다한다.)
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 | #include <stdio.h> struct data { char a; int b; }__attribute__((packed)); int main() { struct data data_type_var; printf("char : %lu Byte\n", (unsigned long)sizeof(char)); printf("int : %lu Byte\n", (unsigned long)sizeof(int)); printf("struct data : %lu Byte\n",(unsigned long)sizeof(struct data)); data_type_var.a = 'A'; data_type_var.b = 100; printf("data_type_var.a : %c\n",data_type_var.a); printf("data_tyoe_var.b : %d\n",data_type_var.b); return 0; } | cs |
위 소스와 달라진 점은 struct(구조체)가 끝나는 시점에 __attribute__((packed));
를 추가해줬다는 것이다 . 의미는 구조체를 정의할때 패딩 없이 채운다는 의미이다.
리눅스 gcc환경에서 가능하고 윈도우(vc) 환경에서는
#pragma pack(push, 1)
struct data{
char a;
int b;
}:
#pragma pack(pop)
를 추가한다
struct data 에서 char 1 int 4 를 해서 5 Byte가 출력되는것을 확인할 수 있다
구조체 초기화
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | #include <stdio.h> struct data { char a; int b; float c; }; int main() { struct data a ={'B', 101 , 1.2}; printf("a.a : %c, a.b: %d, a.c : %f\n" , a.a , a.b , a.c); return 0; } | cs |
---------------------------------------------------------------------------------------------비트 필드
기본 자료형에서 가장 작은 char 형도 1바이트를 차지한다.
그보다 더 작게 비트로 어떻게 선언할 수 있을까 ?
struct 구조체에서 몇 비트를 사용할 것 인지 선언을 한다
main() 내부에서 얼마나 큰 수 (10진수)를 사용할 것인지
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 | #include <stdio.h> struct data { unsigned char a:2; unsigned char b:2; unsigned char c:4; }; int main() { struct data a; a.a = 2; a.b = 1; a.c =1; printf("struct data : %lu\n" , (unsigned long)sizeof(struct data)); printf("a.a : %d\n" , a.a); printf("a.b : %d\n" , a.b); printf("a.c : %d\n" , a.c); return 0; } | cs |
2^2 혹은 2^4 이상의 수를 주면 오버 플로우가 발생한다
---------------------------------------------------------------------------------------------공용체
공용체는 구조체와 비슷한 문법을 갖고 있고 형태도 비슷하지만 구조체와 달리 멤버들이 하나의 메모리 공간을 공유해서 사용한다는 점에서 다른 특징을 갖고 있다.
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 | #include <stdio.h> 2 3 union data 4 { 5 char a; 6 int b; 7 }; 8 9 int main(void) 10 { 11 union data data_type_var; 12 13 printf("union data : %luByte\n",(unsigned long)sizeof(union data)); 14 printf("union data a : %luByte\n",(unsigned long)sizeof(data_type_var.a)); 15 printf("union data b : %luByte\n",(unsigned long)sizeof(data_type_var.b)); 16 17 data_type_var.b = 0x11223344; 18 19 printf("data_type_var.a : %x\n" , data_type_var.a); 20 printf("data_type_var.b : %x\n" , data_type_var.b); 21 22 data_type_var.a = 0x55; 23 24 printf("data_type_var.a : %x\n" , data_type_var.a); 25 printf("data_type_var.b : %x\n" , data_type_var.b); 26 27 return 0; 28 } 29 30 | cs |
union data는 크기가 가장 큰 b의 4BYTE를 따라가고 있다 .
17행에서 data_type_var.b = 0x11223344;
를 선언하였고 var.a에서 44를 나타내는걸 보면 같은 메모리를 공유하고 있는 것을 확인 할 수 있다 .
22행에서 data_type_var.a = 0x55;
를 선언하였고 var.a 결과가 55 나왔다.
var.b의 값이 11223355가 나왔고 같은 메모리를 공유하고 있는 것을 확인 할 수 있다.
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 | #include <stdio.h> struct data { union { struct { char data_a; int data_b; }; struct { char a; int b; }; }; }; int main(void) { struct data data; data.a = 1; data.data_b = 2; printf("data.data_a : %d\n", data.data_a); printf("data.data_b : %d\n", data.data_b); printf("data.a : %d\n", data.a); printf("data.b : %d\n", data.b); return 0; } | cs |
다른 구조체이지만 한 공용체 안에 들어있기 때문에 같은 메모리 공간을 공유하고있다.
그렇기 떄문에 서로 다른 변수 이름으로 같은 값을 갖게 된다 .
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 38 | #include <stdio.h> enum day {MON, TUE, WED, THU, FRI, SAT, SUN}; enum test {A=100,B=103,C}; int main() { enum day d; d = MON; printf("MON : %d, TUE : %d, WED : %d, THU : %d , FRI : %d , SAT : %d , SUN : %d\n",MON,TUE,WED,THU,FRI,SAT,SUN); printf("A : %d , B : %d , C : %d\n" , A ,B ,C); switch(d) { case MON: printf("Ang\n"); printf("\n"); break; case TUE: break; case WED: break; case THU: break; case FRI: break; case SAT: break; case SUN: break; } return 0; } | cs |