일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- C언어 #부록
- C++ 언어 # 핵심 정리
- shell_script
- C언어 # 부록
- PHP #핵심정리
- C++ 언어 #핵심정리
- C언어 #핵심정리
- HTML #핵심정리
- C++ 언어 # 핵심정리
- Bandit
- Hacking #Baic
- MySQL #핵심정리
- C언어 # 핵심 정리
- Today
- Total
cCcode
C Language [핵심정리] - 32 본문
1. 구조체와 공용체 활용하기
오늘은 구조체와 공용체를 혼용해보겠습니다.
지금까지는 구조체의 멤버로 일반 변수들만 사용했었죠. 하지만 구조체는 멤버로 일반 변수 뿐만 아니라 구조체를 멤버로 가질 수 있습니다.
구조체를 멤버로 가진 구조체는 그전과 마찬가지로 .을 사용해 계층적인 구조로 접근하시면 됩니다. 이중 포인터에 값을 할당하는 느낌이랄까요..? 여기서 주의해야 할 점은 구조체의 멤버로 들어갈 구조체를 먼저 선언해주어야 한다는 점입니다.
만약 멤버 구조체 보다 구조체를 멤버로 갖는 구조체가 먼저 선언된다면
겉보기에는 이상이 없겠지만
엄청난 수의 에러 향연을 보실 수 있습니다. 실행이 되지 않는 건 당연하고요. 그렇지만 아예 방법이 없다는 건 아닙니다.
이처럼 전방선언(forward declaration)을 사용해 정의되지 않은 구조체를 사용할 수 있습니다. 이게 가능한 이유는 struct Emergemcy(전방 선언)과 실제 구조체 멤버 선언 사이에 멤버를 사용하는 부분이 없었기에 가능했습니다.
제가 이렇게 구조체 사이에 main 함수를 위치시켜서 Emergency_Number의 멤버들이 선언되기전 해당 구조체의 멤버로 접근하면 당연히
될리가 없죠.
구조체 변수를 선언함과 동시에 구조체 안에 들어있는 구조체 멤버까지 초기화하려면 { } 중괄호를 사용하면 됩니다. 중괄호는 선언할 때만 사용할 수 있는 거 아시죠..?
이번에는 구조체 안 구조체 멤버에 메모리를 할당해보겠습니다.
여기서 s1은 포인터 이므로, 화살표 연산자로 접근하지만 s1 즉, Student 의 멤버 Emergency_Number 은 포인터가 아니기에 . 으로 접근합니다. 너무 복잡하게 생각하지마세요. 포인터라면 화살표 연산자 아니면 . 입니다.
만약 구조체의 멤버 구조체가 포인터라면?
이 경우에는 방금 말씀드린대로 포인터의 조합이므로 ->(화살표 연산자)를 사용합니다. 다만, 전과는 달리 포인터의 해제 순서 또한 주의해야 하는데요. 해제할 때는 반드시 안 쪽의 멤버 순으로 해제 해야합니다. 아니면 안의 주소를 다른 공간에 임시로 저장해둔다면 바깥에 있는 포인터를 먼저 해제해도 되긴 합니다만...
헷갈리실 수 있으니 포인터 해제는 안쪽부터 라고 알아두시면 되겠습니다.
이제 대망의 구조체와 공용체의 혼용입니다!
간단하게 위에 코드에서 사용한 개념에 대해 설명드리겠습니다.
아마 여러분들이 위 코드를 보시고 든 제일 큰 의문은 union의 멤버 position이 왜? 그 안의 struct 멤버에 접근하여 수정할수 있는가? 일텐데요. 우선 공용체의 개념은 공간을 공유하는 데 있습니다.
여기서 이해가 안되시는 분이 나올 수도 있습니다. "어? 공간을 공유하니까 한 변수가 공간을 차지하면 다른 변수는 사용 못하기 때문에 값이 이상하게 나와야 하는거 아닌가?"라고 말이죠. 여기서 헷갈리시면 안되는 게 공간을 공유한다는 건 하나의 변수가 그 공간을 사용했을 때 계속 그 공간을 독차지 하는 게 아닙니다.
굳이 비유하자면 공공재에 가깝겠네요. 모두가 사용해야하니 쓰고 돌려주는 느낌이라고 하면 이해하기 편하실까요?
예시를 들어볼게요.
이처럼 돌아가면서 사용합니다. 이해 되셨으면 좋겠네요.
다만 여기서 배열에 값을 준다면
배열에는 첫 번째 인덱스 값만이 아닌 모든 값이 들어갑니다. 왜냐하면 공용체에서 배열 자체를 하나의 공간으로 취급하거든요.
int 자료형(4byte) x 3 배열 = 12byte
여기서 제가 공간을 공유한다고 말씀드렸죠? 그럼 배열 크기로 공간이 들어갔을 때 해당 공용체에 다른 배열이 존재 한다면 그 배열의 값들은 어떻게 될까요?
이와 같이 각 인덱스에 같은 값이 들어가는 걸 확인할 수 있습니다.
즉, 저어어어기 위에 코드에서 가장 안쪽의 struct 는 변수들의 모음 배열의 역할을 해주고 있다고 볼 수 있습니다.
여기서 익명 구조체는 독립적인 공간에 저장하고(방금 말씀드린것처럼 배열 또한 독립적인 값의 모음 입니다.) 구조체.멤버(x, y, z) 와 같은 방식으로 바로 접근하기 위해 사용하였으며, 익명 공용체 또한 공용체.멤버(Position)처럼 바로 접근하기 위해 사용하였습니다.
아래 문제를 풀어서 이해를 제대로 하셨는지 확인해보세요.
https://codeup.kr/problem.php?id=1420
Hint. 구조체를 활용하세요.
정답.


3등을 찾는 과정에서 간단한 연산이 수행되었습니다.
알아두시면 유용하니 집중해서 봐주세요.
ex) 98 48 65 33
1) 각 정수에 1 이라는 순위를 부여합니다. (그러러면 구조체를 사용해야겠죠?)
98 - 1, 48 - 1, 65 - 1, 33 - 1
2) 이제 이중 for문을 돌리며 첫 번째 정수부터 차례대로 비교하다 자신보다 큰 숫자가 있다면 순위에 + 1을 합니다.
ex) for (i = 0; i < 4; i++), for (j = 0; j < 4; j++)
i = 0 인 경우
j(0) = 1(순위), j(1) = 1(순위), j(2) = 1(순위), j(3) = 1(순위) -> 98 = 1순위
i = 1 인 경우
j(0) = 2(순위), j(1) = 2(순위), j(2) = 3(순위), j(3) = 3(순위) -> 48 = 3순위
i = 3 인 경우
j(0) = 2(순위), j(1) = 2(순위), j(2) = 2(순위), j(3) = 2(순위) -> 65 = 2순위
i = 4 인 경우
j(0) = 2(순위), j(1) = 3(순위), j(2) = 4(순위), j(3) = 4(순위) -> 33 = 4순위
다시 말씀드리지만 정답은 하나가 아닙니다.
이제 C언어 핵심정리도 끝을 향해 달려가네요.
'C Language Basic' 카테고리의 다른 글
C Language [핵심정리] - 34 (0) | 2021.07.01 |
---|---|
C Language [핵심정리] - 33 (0) | 2021.06.29 |
C Language [핵심정리] - 31 (1) | 2021.06.21 |
[부록] 산술 연산 계산기 (완성본) (0) | 2021.06.19 |
C Language [핵심정리] - 29 (0) | 2021.06.15 |