본문 바로가기
Computer Science/C 언어

[C언어 19] Advanced Uses of Pointers 포인터의 고급 활용

by rnasterofmysea 2024. 12. 27.
반응형

Advanced Uses of Pointers / 포인터의 고급 활용


1. Dynamic Memory Allocation / 동적 메모리 할당

  • 개념: 프로그램 실행 중 메모리를 동적으로 할당하고 해제.
  • 주요 함수:
    • malloc: 메모리를 할당.
    • calloc: 초기화된 메모리를 할당.
    • realloc: 기존 메모리 크기를 조정.
    • free: 할당된 메모리를 해제.

(1) malloc

  • 설명: 지정한 크기의 메모리를 할당하며, 초기화되지 않은 상태로 반환.
  • 형식: void *malloc(size_t size);

예제:

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

int main() {
    int *arr = malloc(5 * sizeof(int)); // 정수 5개 크기의 메모리 할당
    if (arr == NULL) {
        perror("malloc 실패");
        return 1;
    }

    for (int i = 0; i < 5; i++) {
        arr[i] = i + 1;
    }

    printf("malloc으로 할당된 메모리 값: ");
    for (int i = 0; i < 5; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");

    free(arr); // 메모리 해제
    return 0;
}

(2) calloc

  • 설명: 지정한 크기의 메모리를 할당하고, 0으로 초기화.
  • 형식: void *calloc(size_t nmemb, size_t size);

예제:

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

int main() {
    int *arr = calloc(5, sizeof(int)); // 정수 5개 크기의 메모리 할당 및 초기화
    if (arr == NULL) {
        perror("calloc 실패");
        return 1;
    }

    printf("calloc으로 초기화된 메모리 값: ");
    for (int i = 0; i < 5; i++) {
        printf("%d ", arr[i]); // 모든 값이 0으로 초기화됨
    }
    printf("\n");

    free(arr); // 메모리 해제
    return 0;
}

(3) realloc

  • 설명: 기존 메모리 크기를 조정하거나 확장.
  • 형식: void *realloc(void *ptr, size_t size);

예제:

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

int main() {
    int *arr = malloc(3 * sizeof(int)); // 정수 3개 크기의 메모리 할당
    if (arr == NULL) {
        perror("malloc 실패");
        return 1;
    }

    for (int i = 0; i < 3; i++) {
        arr[i] = i + 1;
    }

    printf("realloc 이전 값: ");
    for (int i = 0; i < 3; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");

    arr = realloc(arr, 5 * sizeof(int)); // 메모리 크기를 5개로 확장
    if (arr == NULL) {
        perror("realloc 실패");
        return 1;
    }

    for (int i = 3; i < 5; i++) {
        arr[i] = i + 1; // 추가된 공간 초기화
    }

    printf("realloc 이후 값: ");
    for (int i = 0; i < 5; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");

    free(arr); // 메모리 해제
    return 0;
}

(4) free

  • 설명: 동적으로 할당된 메모리를 해제.
  • 형식: void free(void *ptr);

예제:

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

int main() {
    int *arr = malloc(5 * sizeof(int)); // 동적 메모리 할당
    if (arr == NULL) {
        perror("malloc 실패");
        return 1;
    }

    for (int i = 0; i < 5; i++) {
        arr[i] = i + 1;
    }

    printf("메모리 값: ");
    for (int i = 0; i < 5; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");

    free(arr); // 메모리 해제
    printf("메모리 해제 완료\n");

    return 0;
}

2. Function Pointers / 함수 포인터

  • 개념: 함수를 가리키는 포인터를 사용하여 동적으로 함수를 호출.
  • 주요 활용:
    • 콜백 함수 구현.
    • 동적 함수 호출.

예제: 함수 포인터 사용

#include <stdio.h>

void say_hello() {
    printf("Hello, World!\n");
}

void say_goodbye() {
    printf("Goodbye, World!\n");
}

int main() {
    void (*func_ptr)(); // 함수 포인터 선언

    func_ptr = say_hello;
    func_ptr(); // Hello, World!

    func_ptr = say_goodbye;
    func_ptr(); // Goodbye, World!

    return 0;
}

3. Array of Pointers / 포인터 배열

  • 개념: 포인터 배열을 사용하여 여러 문자열이나 다차원 데이터를 저장.

예제: 문자열 배열 관리

#include <stdio.h>

int main() {
    const char *messages[] = {"Hello", "World", "C Programming"};

    for (int i = 0; i < 3; i++) {
        printf("%s\n", messages[i]);
    }

    return 0;
}

4. Pointer to Pointer / 이중 포인터

  • 개념: 포인터를 가리키는 포인터를 사용하여 동적 메모리를 관리하거나 복잡한 데이터 구조를 처리.

예제: 이중 포인터를 이용한 2D 배열 동적 할당

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

int main() {
    int rows = 3, cols = 4;
    int **matrix = malloc(rows * sizeof(int *));

    for (int i = 0; i < rows; i++) {
        matrix[i] = malloc(cols * sizeof(int));
        for (int j = 0; j < cols; j++) {
            matrix[i][j] = i * cols + j;
        }
    }

    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < cols; j++) {
            printf("%d ", matrix[i][j]);
        }
        printf("\n");
        free(matrix[i]);
    }

    free(matrix);
    return 0;
}

5. Void Pointers / void 포인터

  • 개념: 특정 데이터 타입에 구애받지 않는 포인터. 타입 캐스팅이 필요.

예제: void 포인터 사용

#include <stdio.h>

void print_value(void *ptr, char type) {
    switch (type) {
        case 'i':
            printf("정수: %d\n", *(int *)ptr);
            break;
        case 'f':
            printf("실수: %f\n", *(float *)ptr);
            break;
        case 'c':
            printf("문자: %c\n", *(char *)ptr);
            break;
    }
}

int main() {
    int num = 42;
    float pi = 3.14f;
    char letter = 'A';

    print_value(&num, 'i');
    print_value(&pi, 'f');
    print_value(&letter, 'c');

    return 0;
}

6. Linked Lists / 연결 리스트

  • 개념: 포인터를 사용하여 노드를 동적으로 연결.
  • 활용:
    • 데이터 삽입 및 삭제가 빈번한 상황에서 효율적.

예제: 연결 리스트 구현

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

typedef struct Node {
    int data;
    struct Node *next;
} Node;

void print_list(Node *head) {
    while (head != NULL) {
        printf("%d -> ", head->data);
        head = head->next;
    }
    printf("NULL\n");
}

int main() {
    Node *head = malloc(sizeof(Node));
    Node *second = malloc(sizeof(Node));
    Node *third = malloc(sizeof(Node));

    head->data = 1;
    head->next = second;

    second->data = 2;
    second->next = third;

    third->data = 3;
    third->next = NULL;

    print_list(head);

    free(third);
    free(second);
    free(head);
    return 0;
}

포인터 사용에 대해 연습하는 좋은 방법은 알고리즘 문제를 직접 풀어보는 것이라고 생각합니다.

알고리즘 & 자료구조 카테고리를 참조해주세요!

 

https://rnasterofmysea.tistory.com/category/Computer%20Science/%EC%9E%90%EB%A3%8C%EA%B5%AC%EC%A1%B0%20%26%20%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98

 

'Computer Science/자료구조 & 알고리즘' 카테고리의 글 목록

 

rnasterofmysea.tistory.com

https://rnasterofmysea.tistory.com/category/Computer%20Science/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98%20%EB%AC%B8%EC%A0%9C

 

'Computer Science/알고리즘 문제' 카테고리의 글 목록

 

rnasterofmysea.tistory.com

 

 


 

💡 도움이 되셨다면 댓글과 공감 부탁드립니다! 😊
📌 더 많은 알고리즘 풀이와 프로그래밍 자료는 블로그에서 확인하세요!
✉️ 문의나 피드백은 댓글이나 이메일로 남겨주세요.

 

반응형