노는게 제일 좋습니다.
18회차(끝) : 구조체 초기화, 비트 구조체, 공용체 본문
0. 참고 자료
http://soen.kr/
1. 구조체 초기화
구조체의 멤버들은 마치 배열을 초기화하듯 초기화할 수 있다. 별거없다.
struct b {
int apple;
int banana;
};
struct a {
struct b bb;
int tomato;
};
struct a plug = { {1,2},3 };
printf("%d %d %d\n", plug.bb.apple, plug.bb.banana, plug.tomato);
2. 구조체의 대입
구조체는 같은 모양이면 대입할 수 있다. 멤버들을 덮어씌우는 것이다.
struct strt {
int one;
int two;
};
struct strt a = { 1,2 };
struct strt b=a;
printf("%d %d", b.one, b.two);
위 예제는 strt태그로부터 구조체 a,b를 만든다. 그리고 b에 a를 대입한다.
이게 가능하다는 것은, 구조체가 좌변값이라는 것. 함수 인수로 받을 수도 있고, 리턴하는데 구조체를 쓸 수 있다.
b=a 구문은 memcpy(&b, &a, sizeof(a)); 와 같다. 메모리를 푹 퍼다가 복사해주는 것이다.
3. 깊은 복사와 얕은 복사
struct strt {
char *pc;
};
struct strt a = { NULL };
struct strt b;
a.pc = malloc(32);
strcpy_s(a.pc,sizeof("helololollooo"),"helololollooo");
b = a;
printf("%s %s\n", a.pc, b.pc);
strcpy_s(a.pc, sizeof("goodbyeeeyee"), "goodbyeeeyee");
printf("%s %s\n", a.pc, b.pc);
위 코드는 a.pc에 "hellololo"비슷한걸 복사하고난뒤에, b=a를 한다.
이후에 a.pc가 가리키는 문자열의 내용을 바꿨더니 b.pc도 바뀐다.
이것은 b.pc에 a.pc의 값 그 자체가 단순히 복사되어 들어갔기 때문이다. helolollolo 문자열이 아닌, 포인터를 복사했다는 말이다.
잘못됐다는 것이 아니라, 이런 현상이 일어나기 때문에 대입했을 때 의도치않은 상황이 생길 수 있다는 것이다.
이와 같이 그냥 단순히 복사만 하는 것을 '얕은 복사' 라고 한다.
반면 '깊은 복사'는 포인터를 복사하는게 아니고, 포인터를 따라가면 나오는 그 값을 취한다.
즉, b=a를 할 때 깊은 복사가 일어났다면, a.pc 라는 포인터가 b.pc로 대입되지 않는다.
b.pc는 새로운 공간을 할당한 뒤에, "helololllo"를 여기에 기록한다.
b = a;
b.pc = malloc(32);
strcpy_s(b.pc, strlen(a.pc)+1, a.pc);
위는 깊은 복사의 한 예이다. b에 일단 a를 대입한다. 그 다음 b에다가는 a포인터를 따라가면 나오는 "helololo"따위의 상수를 기록해준다.
4. 비트 구조체
비트들을 멤버로 가지는 구조체이다.
struct tag_bit {
unsigned int a : 4;
unsigned int b : 8;
unsigned int c : 4;
};
위 코드는 비트 구조체를 정의한 것이다. 타입 멤버이름 : 비트수; 의 형식으로 멤버들을 적어준다.
위의 경우 총 16비트 = 2바이트를 차지한다. 비트들은 먼저 쓰인것이 일반적으로 하위비트(작은 자리)로 들어간다.
예를 들어, 0101 00110101 1110 이렇게 2바이트 코드가 있을 때, 맨뒤 1110을 a가 나타내고, 맨앞 0101을 c가 나타낸다.
struct tag_bit {
unsigned int a : 4;
unsigned int : 0;
unsigned int c : 4;
};
만약 이렇게 크기를 0으로 주면, 해당 워드에서 사용되지 않은 비트는 모두 버린다.
c는 그 다음 워드에서 시작한다. 구조체 패딩과 비슷한 맥락에서 이해할 수 있겠다.
물론, 비트 필드가 구조체에 쓰였다고 해서 우리가 늘상 쓰던 멤버를 쓸 수 없는 것은 아니다. 섞어써도 된다.
5. 공용체
공용체는 구조체와 문법이 유사하나, 멤버들이 기억공간을 공유한다는 특징을 가진다.
union {
int a;
char b[10];
}unab;
위와 같은 코드로 unab라는 이름의 공용체를 하나 정의했다. 여기서 a의 주소와 b의 주소는 같다.
즉, a값이 바뀌면 b값도 바뀐다. b값이 바뀌면 마찬가지로 a값도 바뀐다.
공용체의 크기는 가장 큰 멤버의 크기와 같다.
하나의 정보를 나타내는데 여러 형식으로 나타내고 싶을 때 공용체를 사용한다.
'C' 카테고리의 다른 글
17회차 : 구조체 정의, 구조체 멤버 참조 (0) | 2017.03.02 |
---|---|
16회차 : 문자열 함수, 수치와 문자열 (0) | 2017.03.01 |
15회차 : 배열 포인터, 배열과 문자열 (0) | 2017.02.26 |
14회차 : 첨자 연산, 포인터 배열 (0) | 2017.02.23 |
13회차 : 동적 메모리 할당, 이중 포인터 (0) | 2017.02.20 |