Search
Duplicate
👉

[Libft/ft_lst] 왜 더블포인터이여야만 할까?

간단소개
팔만코딩경 컨트리뷰터
ContributorNotionAccount
주제 / 분류
42cursus
포인터
C
Scrap
태그
더블포인터
포인터
9 more properties

Libft의 Bonus 과제의 함수들의 프로토타입을 살펴보자.

Libft의 Bonus에서는 링크드리스트를 다루게 된다. 제목과 관련하여 아래의 프로토타입을 잘 살펴보자. lst로 주어지는 파라미터의 type에 어떤 것은 포인터, 어떤 것은 더블포인터이다. 그 이유에 대해서 생각해 본적이 있는가?
Libft의 Bonus 과제의 프로토타입들

더블포인터이여야만 할까?

ft_lstadd_back 함수에 대한 필자의 구현은 아래와 같다. 너무 당연한 코드의 형태이다. 여기서 제목에 대한 의문점을 떠올려보자. 파라미터 lst의 타입이 t_list *lst이여도 괜찮을까?
정상코드

* 하나만 빼면 되잖아?

아래와 같이 코드를 수정해보자. lst에 붙은 * 하나씩만 제거했다. 타입도 모두 맞고, 왠지 동작이 될 것 같은 느낌이 든다. 당연히(?) 제대로 동작하지 않는다.
비정상코드

Piscine의 기억을 되살려보자.

Piscine에서 포인터를 다루는 방법을 익히는 것
이 목적인 초반 과제 swap함수를 기억하나요? swap함수의 동작을 복기해 봅시다.
swap 함수는 2 개의 int형 포인터를 받아, 역참조를 통해 a 와 b의 값을 바꾸는 함수입니다.
swap 함수

change_to_42함수를 구현하실 수 있나요?

swap 함수를 통해 a와 b의 값을 변경한 것처럼, 파라미터로 넘겨준 c의 값을 42로 변경하는 change_to_42함수를 주어진 프로토타입형태로 구현하실 수 있나요?
change_to_42 구현은 불가능

불가능한가요? 그게 바로 더블포인터이여야만 하는 까닭입니다!

ft_lstadd_back함수가 어떻게 동작해야만 하는지 살펴봅시다.
포인터 & 더블포인터 형태 인자
main 함수에서 링크드리스트 첫번째 노드(==head)를 가리킬 t_list *head를 선언합니다. ft_lstnew함수를 통해 새로운 링크드리스트 노드를 생성 후, t_list *new_node에 할당합니다. 그리고 ft_lstadd_back함수에 headnew_node를 인자로 넘겨줍니다.
함수 호출의 결과는 어떻게 되어야 할까요? 비어있는 링크드리스트였기 때문에, head는 인자로 넘겨준 new_node를 가리켜야합니다. 즉, head의 값은 new_node가 가리키는 노드의 주소, 포인터 new_node의 값과 동일해야 합니다.
main에서 선언된 값 a와 b의 값을 서로 바꾸는 swap함수와 c의 값을 42로 바꾸는 change_to_42함수와 head의 값을 new_node의 값으로 바꾸는 ft_lstadd_back의 동작이 서로 비슷하게 느껴지지 않나요?

주소에 의한 참조  에 의한 참조

함수에 인자를 넘길때 위와 같은 표현을 들어보신적이 있을겁니다. 여기서 주소이 대체 무엇을 의미하는 것일까요? ‘값에 의한 참조는 복사된다 & 그래서 원본이 변하지 않는다.’ 이런 표현도 기억날 수 있습니다. 여기서 복사란 무엇인가요? 무엇이 대체 함수의 파라미터로 넘어가는 것일까요?
주의! 설명을 위한 표현으로 앞으로 부정확한 표현이 등장할 가능성이 다소 존재합니다.

결국은 데이터(0과 1의 집합)와 주소

모든 변수는 데이터주소를 가집니다. 그리고 파라미터로 넘어가는 것은 결국 데이터입니다. (데이터는 제가 설명을 위해 사용할 용어(?)입니다.)
long lt_list *head 모두 8byte 크기의 데이터와 8byte 크기의 주소를 가집니다. 여기서 l이 가진 데이터의 역할(?)은 long이라는 정수를 나타내는것이고, head가 가진 데이터의 역할t_list를 가리키는 포인터 라는 것입니다.
ft_lstadd_back(t_list *lst, t_list *new) 의 경우, t_list *lst 는 NULL의 값을 가질 것이고, 이것으로 할 수 있는 것은 없습니다. main에서 선언된 t_list *head에 접근할 방도가 없습니다. 즉, head의 데이터를 수정하는 것은 불가능합니다.
ft_lstadd_back(t_list **lst, t_list *new) 의 경우, t_list **lstmain에서 선언된 t_list *head의 주소값입니다. 해당 주소값을 역참조하여 head에 접근하여 데이터를 수정하는 것이 가능합니다.

마무리

main에서 선언된 t_list *head데이터주소를 갖습니다. 가진 데이터의 역할은 링크드리스트의 첫번째 노드의 주소, 즉 t_list 포인터 입니다. 어쨋거나 해당 데이터를 변경하기 위해서는, 접근할 수 있는 방법을 제공해야합니다. 그래서 ft_lstadd_back 함수에 head의 주소라는 데이터를 넘겨줍니다. 그리고 head의 주소t_list ** 타입이 될 수 밖에 없습니다. 바로 이것이 해당 프로토타입에서 더블포인터여야만 했던 이유입니다.