Krafton Jungle/2. Keywords

[WEEK04] 포인터와 연결리스트

munsik22 2025. 4. 7. 11:17

포인터란?

포인터(pointer)는 다른 변수의 메모리 주소를 저장하는 변수이다. 쉽게 말하면 "이 변수가 어디에 있는지"를 가리키는 주소를 저장하는 것이다.

int a = 10;
int *p = &a; // p는 a의 주소를 저장

& 연산자 (주소 연산자)

  • 변수 앞에 &를 붙이면 그 변수의 메모리 주소를 가져온다.
  • 예: &a는 변수 a의 주소

* 연산자 (역참조 연산자)

  • 포인터 변수 앞에 *를 붙이면 해당 주소에 저장된 값을 참조하게 된다.
  • 예: *p는 포인터 p가 가리키는 주소에 있는 값을 가져온다.
#include <stdio.h>

int main() {
    int a = 42;
    int *ptr = &a;

    printf("a의 값: %d\n", a);
    printf("a의 주소: %p\n", &a);
    printf("ptr이 저장한 주소: %p\n", ptr);
    printf("ptr이 가리키는 값: %d\n", *ptr);

    return 0;
}

코드 실행 결과


포인터를 활용한 Linked List 구현

포인터가 왜 중요한지를 가장 잘 보여주는 예시 중 하나는 바로 연결 리스트(Linked List) 다. 연결 리스트는 각 노드가 다음 노드의 주소를 가지고 있어, 동적 자료구조를 구현할 때 자주 사용된다.

Linked List 기본 구조

#include <stdio.h>
#include <stdlib.h>

// 노드 구조체 정의
typedef struct Node {
    int data;
    struct Node* next;
} Node;

// 노드 생성 함수
Node* createNode(int data) {
    Node* newNode = (Node*)malloc(sizeof(Node));
    newNode->data = data;
    newNode->next = NULL;
    return newNode;
}

// 리스트에 노드 추가
void appendNode(Node** head, int data) {
    Node* newNode = createNode(data);
    if (*head == NULL) {
        *head = newNode;
    } else {
        Node* current = *head;
        while (current->next != NULL)
            current = current->next;
        current->next = newNode;
    }
}

// 리스트 출력
void printList(Node* head) {
    Node* current = head;
    while (current != NULL) {
        printf("%d -> ", current->data);
        current = current->next;
    }
    printf("NULL\n");
}

// 메모리 해제
void freeList(Node* head) {
    Node* temp;
    while (head != NULL) {
        temp = head;
        head = head->next;
        free(temp);
    }
}

// main 함수
int main() {
    Node* head = NULL;

    appendNode(&head, 10);
    appendNode(&head, 20);
    appendNode(&head, 30);

    printf("Linked List: ");
    printList(head);

    freeList(head);
    return 0;
}

정리

개념 설명
& 연산자 변수의 주소를 가져올 때 사용
* 연산자 포인터가 가리키는 주소의 값을 참조할 때 사용
포인터 변수의 주소를 저장하는 변수
Linked List 포인터를 이용해 동적으로 연결된 자료구조 구현 가능

(cf) 파이썬에서는 C와 같은 직접적인 포인터 개념이 없지만, 리스트나 딕셔너리 같은 자료형을 사용하여 유사한 기능을 구현할 수 있다.

# 변수 a를 리스트로 감싸기
a = [42]

# a의 값 출력
print("a의 값:", a[0])
# a의 주소 출력 (id() 함수를 사용하여 메모리 주소를 확인)
print("a의 주소:", id(a))
# ptr이 저장한 주소 (리스트의 주소를 사용)
ptr = a
print("ptr이 저장한 주소:", id(ptr))
# ptr이 가리키는 값
print("ptr이 가리키는 값:", ptr[0])

위 코드에서 a는 리스트로 감싸져 있으며, 이를 통해 ptr이 a를 참조하는 방식으로 동작한다. id() 함수를 사용하여 변수의 메모리 주소를 확인할 수 있다.

'Krafton Jungle > 2. Keywords' 카테고리의 다른 글

[WEEK05] 가상화  (0) 2025.04.10
[WEEK05] GCC  (0) 2025.04.10
[WEEK04] 그리디 알고리즘  (0) 2025.04.03
[WEEK04] 동적 프로그래밍 (DP)  (0) 2025.04.03
[WEEK03] 위상 정렬  (0) 2025.03.31