전공수업과정 공부중 헷갈리는 부분을 정리하고자 한다.
1. 포인터
C에서 int, char, 포인터 변수는 각각 다음 형태의 값을 저장한다.
- char : 문자형 값
- int : 정수형 값
- 포인터 : 메모리 주소
- &는 주소 연산자로, 해당 변수의 메모리 주소값을 반환한다.
- *는 간접지정 연산자로, 해당 메모리 주소값에 저장된 값에 접근한다. 위 문법을 통해 다음과 같은 연산이 이루어진다.
참고
Q. ptr에 저장된 값은 num의 주솟값인 &num이라 했는데, 그럼 이번엔 &ptr을 출력하면 어떤 값이 나올까?
A. 당연하게도 ptr 포인터 변수의 주소값인 0104가 출력된다. 포인터 변수도 기본 변수와 마찬가지로 메모리 영역에 선언되기 때문이다.
2. 배열과 포인터
배열은 연속된 데이터를 저장하기 위한 자료형으로, 각 데이터들에 대해 인덱스로 접근할 수 있다. 이때 인덱스도 주소를 통해 표현되기에, 포인터로 표현이 가능하다.
또한 배열에 저장된 값들의 메모리 주소는 서로 인접해있기에 다음과 같이 표현될 수 있다.
배열의 각 요소(데이터)에 할당된 메모리 크기는 해당 데이터의 자료형에 따라 결정된다. 따라서 포인터를 1 증가시키면 메모리 주소는 해당 자료형의 크기만큼 증가한다.
3. 함수와 포인터
1) 함수에 기본 변수 전달하기
다음 코드를 실행해보자. 과연 3 -> 10이 출력될까?
하지만 예상과 다르게 그대로 3이 출력된다. 그 이유는 C에서는 함수에 매개변수를 넘길 때 해당 변수의 값을 복사해서 넘기기 때문이다.
따라서 함수에 매개변수를 넘겨 값을 변경하고 싶을 때는 포인터를 이용한다. (추가적으로 별개의 포인터 변수는 선언하지 않아도 된다.)
2) 함수에 포인터 변수 전달하기
함수에 포인터 변수를 매개변수로 넘기는 방법은 다음과 같다. 원리는 곰곰이 생각해보자.
4. 이중 포인터
이중 포인터는 말 그대로 포인터의 포인터을 말한다. 함수에서 int형 변수의 값을 변경할 때 다음과 같이 int형 포인터를 사용한다.
포인터도 마찬가지로 함수에서 int형 포인터의 값을 변경할 때, int형 포인터의 포인터를 사용한다.
추가로 이중 포인터에 대한 포인터는 삼중 포인터이라 하며, n중 포인터의 포인터는 n+1중 포인터라 한다. 크게 어려운 개념은 아니다.
5. 이중 포인터의 사용 예 (연결 리스트)
이중 포인터의 대표적인 사용 사례는 연결 리스트(Linked List)의 구현에서 찾아볼 수 있다.
1) Node형 포인터
연결 리스트는 Node의 연결 상태로 표현되는데, Node 간의 연결 상태는 포인터로 표현되야 한다. 따라서 전체 노드의 시작점인 head는 Node형 포인터로 선언한다.
2) Node형 이중 포인터
연결 리스트에서 사용되는 함수의 매개변수는 다음과 같다.
- insert / delete의 매개변수 : head의 이중 포인터
- print의 매개변수 : head의 포인터
우선 print 함수부터 보자.
print 함수는 아래 로직으로 실행되며, main 함수의 head의 기존값을 변경시키지 않는다.
3) 1중 Node 포인터로 insert 구현
그럼 이번엔 insert 함수를 보자.
왜 이중포인터를 썼는지 감이 안 온다. 그럼 위 코드에서 insert의 인자를 1중 Node형 포인터로 바꾼 뒤 동작을 보면 다음과 같다.
최종 리스트 결과가 문제없이 나타난다. 아직까지는 문제가 없다.
하지만 만약 Node의 삽입 위치가 head였을 때 로직 수행 결과는 다음과 같다.
새 Node인 nd를 생성한 뒤 insert 함수 내 head가 nd를 가리키게 했지만, 해당 head는 main 함수의 head가 아닌, 함수 내 지역 변수로 선언된 head이기 때문이다. 따라서 insert 함수가 종료되면 해당 head와 nd는 main 함수에서는 가리키는 포인터가 없기 때문에 접근이 불가능하다. 즉, 연결 리스트의 가장 첫번째 Node인 head가 변경될 수가 없어 1중 포인터로는 insert의 로직을 완전히 충족시킬 수 없다.
5) 이중 포인터로 insert 구현 이를 해결하려면 다음과 같이 Node형 이중 포인터를 사용해야 한다.
최종 상태는 다음과 같다.
이렇듯 함수에서 포인터가 가리키는 주소 자체를 바꾸려면, 해당 포인터의 주소값인 포인터의 포인터를 넘겨야 한다.
'공부 STUDY > C | C++' 카테고리의 다른 글
[C] 메모리 구조 | 스택, 힙, 데이터영역 | stack, Heap, Data (0) | 2022.11.29 |
---|---|
[C언어] 헷갈리는 getchar() 함수 이해하기 (0) | 2022.11.24 |
[C언어] 다음 변환 지정자에 해당하는 'scanf_s' 에 대한 정수 인수가 없습니다 (0) | 2022.10.01 |
혼공C | 완독 성공 (0) | 2022.08.07 |
C 언어 | 혼공C 공부기록 (0) | 2022.07.19 |