Linked List 를 C로 구현할 때

CharliePark·2020년 8월 28일
0

TIL

목록 보기
14/67

이 글은 홍정모의 따라하며 배우는 C언어 (부록)>을 공부하고, 과제를 스스로 해결하며 정리한 내용입니다.

먼저 간략하게 따배씨에 감사를 남긴다. C를 점차 더 깊이 이해하면서, C와 C를 잘 공부하는 것의 중요성을 다시금 깨닫고 있는데, 따배씨를 통해서 부족한 부분을 충분히 채워 나가고 있다. 추후 KNK, KnR 이나 컴퓨터 구조 등을 공부할 때도 도움이 많이 될 것이라고 생각한다.

따배씨를 공부하며, 포인터, 이중 포인터, 구조체 등을 배웠고, 주의사항이나 내용 설명을 잘 이해하고 넘어갔었다.

그런데 과제로 코드를 작성하다가 위의 내용과 관련된 문제가 발생했고, 다시금 이해하고 넘어갈 수 있었다.

 

먼저 과제에서 제작한 프로그램을 간단히 설명하자면, 이 프로그램은 영화의 title과 rating이 기록된 txt 파일을 input으로 받고

프로그램 내에서 각 영화를 수정, 추가, 삭제하고 마지막에 output으로 다시 txt파일을 출력하는 프로그램이다.

 

 

프로그램 내에서 print하고 edit하는 작업에는 구조체에 대한 포인터 만으로도 별 문제없이 작동했다.

문제는 연결리스트에서 head를 주고 받을 때 발생했다.

코드의 일부분을 보면서 확인해보자. (전체 코드는 깃헙 에 공개해두었다.)

  void delete_item(struct movie** head_ptr, int index)
  {
      struct movie* temp;

      if (index != 0)
      {
          temp = search_index(*head_ptr, index);

          struct movie* before_deleted = search_index(*head_ptr, index - 1);

          before_deleted->next = temp->next;

          free(temp);
      }

      else
      {
          temp = *head_ptr;
          *head_ptr = (*head_ptr)->next;
          free(temp);
      }

      return;
  }
    

 

대부분의 함수에서 node를 다루는 데 별 문제가 발생하지 않았는데, 이 함수를 포함해서 '첫번째 노드를 가리키는 head를 직접적으로 수정할 때' 문제가 발생했다.

몇 번의 시행착오 후, 디버깅을 통해 함수 내에서 수정됐던 구조체 포인터 변수 'head'가 함수가 return 되고 난 후에는 수정 전 값으로 남아있는 것을 확인했고, 직감적으로 포인터와 관련된 문제임을 알게됐다.

정리하자면 문제는 단순했다.

Linked List의 구조를 생각해보자. Linked List는 여러 개의 데이터가 메모리 곳곳에 위치해있고, 서로를 연결하기 위해 각각의 데이터는 다음 데이터의 주소를 가지고 있다.

이를 C로 구현하면, 각각의 데이터 셋은 구조체로 구현할 수 있고, 그 구조체 안에는 다음 node의 위치를 갖는 주소값이 필요한 것이다.

이렇게 구현된 Linked List를 출력하고 수정하기 위해서는 첫번째 node로부터 순차적으로 읽어서 다루는 과정이 필요했고, 이를 위해 각각의 함수에는 첫번째 node를 가리키는 포인터 변수 head의 '값'을 제공한 상태였다.

이때 첫 노드를 가리키는 head는 '값' 만 제공된 상태라는 것이 중요하다.

 

간단한 예를 들어보자.

첫번째 노드를 삭제하는 기능을 구현하려면, 첫번째 노드를 삭제하고, head가 두번째 node를 가리켜야 한다.

이때, 단순히 head를 value로서 함수에 넘겨주면, 함수는 head가 두번째 node를 가리키게 한 후 반환하는데, 이는 함수에서 빠져나오면서 변경되지 않는 값이 된다.

따라서 이때는 'head 를 포인터로 제공하면' 안되고, 'head의 주소'를 넘겨줘야 head의 값을 바꿀 수 있다. 즉, head가 가리키는 것을 변환하는 게 아니라, head를 직접 바꿔야 하므로 head에 대한 포인터, 즉 이중 포인터를 함수의 인자로 넘겨줘야 하는 것이다.

물론 head를 반환값으로 해서 함수를 구현할 수도 있다.

 

 

사실 이중 포인터에 대한 부분이 그렇게 어려운 부분은 아닌데, 오늘 Array로 되어있던 프로그램을 Linked List로 다시 구현하면서 조금 헷갈렸던 게 있었다. (물론 헷갈리지 않도록 더 정확히 알고 짜는게 중요하다;;)

0개의 댓글