포인터란?

2024. 9. 2. 01:00·개발 일지/C언어
728x90
반응형

C 언어 포인터 완전 정복: 초보자를 위한 친절한 안내서

 

1. 포인터란 무엇일까요? 

  • 컴퓨터는 데이터를 메모리라는 공간에 저장합니다. 각 데이터는 메모리 상의 특정 위치(주소)에 저장되는데, 이 주소를 저장하는 특별한 변수가 바로 포인터입니다.
  • 즉, 포인터는 데이터가 있는 곳을 가리키는 표지판과 같습니다.

2. 왜 포인터를 사용할까요? 

  • 효율적인 메모리 관리: 큰 데이터를 직접 복사하는 대신, 포인터를 이용해 데이터의 위치만 전달하면 메모리 사용량을 줄일 수 있습니다.
  • 함수 간 데이터 공유: 함수에 포인터를 전달하면, 함수 내부에서 원본 데이터를 직접 변경할 수 있습니다.
  • 동적 메모리 할당: 프로그램 실행 중에 필요한 만큼 메모리를 할당하고 해제할 수 있어, 메모리 사용을 유연하게 조절할 수 있습니다.
  • 데이터 구조 구현: 연결 리스트, 트리 등 복잡한 데이터 구조를 구현하는 데 필수적입니다.

3. 포인터 선언 및 사용 

  • 선언: 자료형* 포인터_변수_이름;
    • 예: int* ptr; (int형 데이터의 주소를 저장하는 포인터 ptr 선언)
  • 주소 할당: 포인터_변수_이름 = &변수_이름;
    • & 연산자는 변수의 주소를 가져옵니다.
    • 예: ptr = # (변수 num의 주소를 포인터 ptr에 저장)
  • 간접 참조: *포인터_변수_이름
    • * 연산자는 포인터가 가리키는 곳에 저장된 값을 가져옵니다.
    • 예: printf("%d", *ptr); (ptr이 가리키는 곳에 저장된 값 출력

4. 예시로 이해하기 

#include <stdio.h>

int main() {
    int num = 10;    // num 변수 선언 및 초기화
    int* ptr = &num; // ptr 포인터 선언 및 num의 주소 할당

    printf("num의 값: %d\n", num);        // num 값 출력: 10
    printf("ptr이 가리키는 값: %d\n", *ptr); // ptr이 가리키는 값 출력: 10
    printf("num의 주소: %p\n", &num);      // num의 주소 출력
    printf("ptr의 값: %p\n", ptr);         // ptr의 값(num의 주소) 출력

    *ptr = 20; // ptr이 가리키는 곳의 값 변경
    printf("num의 값 변경 후: %d\n", num); // num 값 출력: 20

    return 0;
}

 

5. 주의 사항 ⚠️

  • NULL 포인터: 어떤 곳도 가리키지 않는 포인터입니다. NULL 포인터를 역참조하면 프로그램이 비정상적으로 종료될 수 있습니다.
  • 댕글링 포인터: 이미 해제된 메모리 영역을 가리키는 포인터입니다. 댕글링 포인터를 사용하면 예측할 수 없는 결과가 발생할 수 있습니다.
  • 잘못된 포인터 연산: 포인터 연산을 잘못하면 메모리 접근 오류가 발생할 수 있습니다.

 

C 언어 포인터 완전 정복: 초보자부터 숙련자까지, 모든 것을 파헤쳐 봅시다!

 

 

1. 포인터의 기본 개념 다시 살펴보기 

  • 포인터: 메모리 상의 주소를 저장하는 특별한 변수입니다.
  • 주소 연산자 (&): 변수의 메모리 주소를 얻는 데 사용합니다.
  • 간접 참조 연산자 (*): 포인터가 가리키는 메모리 위치에 저장된 값에 접근하는 데 사용합니다.

2. 포인터와 배열 

  • 배열 이름은 포인터: 배열 이름은 배열의 첫 번째 요소의 주소를 나타내는 포인터입니다.
  • 배열 요소 접근: 배열_이름[인덱스]와 *(배열_이름 + 인덱스)는 같은 의미입니다.
  • 포인터 연산: 포인터에 정수를 더하거나 빼면, 포인터가 가리키는 메모리 위치가 이동합니다. 이동하는 크기는 포인터의 자료형에 따라 달라집니다.

3. 포인터와 함수 

  • 값에 의한 호출 (Call by Value): 함수에 인자를 전달할 때 값을 복사하여 전달합니다. 함수 내부에서 인자 값을 변경해도 원본 값은 변하지 않습니다.
  • 참조에 의한 호출 (Call by Reference): 함수에 인자를 전달할 때 주소를 전달합니다. 함수 내부에서 포인터를 이용해 원본 값을 직접 변경할 수 있습니다.

4. 포인터와 문자열 

  • 문자열: C 언어에서 문자열은 문자 배열로 표현됩니다.
  • 문자열 포인터: 문자열의 시작 주소를 저장하는 포인터입니다.
  • 문자열 처리 함수: strlen, strcpy, strcat 등 다양한 문자열 처리 함수는 문자열 포인터를 인자로 받습니다.

5. 동적 메모리 할당 

  • malloc: 메모리를 할당하고, 할당된 메모리의 시작 주소를 반환합니다.
  • calloc: 메모리를 할당하고, 0으로 초기화한 후 할당된 메모리의 시작 주소를 반환합니다.
  • realloc: 이미 할당된 메모리의 크기를 변경합니다.
  • free: 할당된 메모리를 해제합니다.

6. 고급 포인터 활용 

  • 함수 포인터: 함수의 주소를 저장하는 포인터입니다. 함수 포인터를 사용하면 함수를 인자로 전달하거나, 실행 시점에 호출할 함수를 결정할 수 있습니다.
  • void 포인터: 어떤 자료형의 주소든 저장할 수 있는 포인터입니다. void 포인터를 사용하면 다양한 자료형의 데이터를 처리하는 함수를 작성할 수 있습니다.
  • 포인터 배열: 포인터를 저장하는 배열입니다. 포인터 배열을 사용하면 여러 개의 포인터를 효율적으로 관리할 수 있습니다.
  • 다중 포인터: 포인터를 가리키는 포인터입니다. 다중 포인터를 사용하면 복잡한 데이터 구조를 구현하거나, 함수에 포인터를 전달하여 함수 내부에서 포인터 값을 변경할 수 있습니다

C 언어 포인터 완전 정복: 심화 학습으로 포인터 마스터 도전! 

 

1. 포인터와 배열: 더 깊이 이해하기

  • 배열과 포인터의 관계: 배열 이름은 상수 포인터이며, 배열의 첫 번째 요소의 주소를 나타냅니다. 하지만 배열 이름 자체는 변경할 수 없습니다.
  • 포인터 산술 연산: 포인터에 정수를 더하거나 빼면, 포인터가 가리키는 메모리 위치가 이동합니다. 이동하는 크기는 포인터의 자료형 크기에 따라 결정됩니다. 예를 들어 int* ptr에 1을 더하면 4바이트(일반적으로 int형 크기)만큼 이동합니다.
  • 다차원 배열과 포인터: 다차원 배열도 포인터를 사용하여 접근할 수 있습니다. 다차원 배열의 각 행은 1차원 배열로 간주되며, 행의 시작 주소를 저장하는 포인터 배열을 사용하여 접근할 수 있습니다.
#include <stdio.h>

int main() {
    int arr[5] = {10, 20, 30, 40, 50};
    int* ptr = arr; // 배열의 첫 번째 요소 주소를 포인터에 저장

    printf("arr[0]: %d, *ptr: %d\n", arr[0], *ptr); // 10, 10
    printf("arr[2]: %d, *(ptr + 2): %d\n", arr[2], *(ptr + 2)); // 30, 30

    ptr += 3; // 포인터를 3칸 이동 (12바이트 이동)
    printf("*ptr: %d\n", *ptr); // 40

    return 0;
}

 

 

  • 배열 arr의 이름은 첫 번째 요소의 주소를 나타내는 포인터입니다.
  • ptr + 2는 세 번째 요소의 주소를 나타내고, *(ptr + 2)는 세 번째 요소의 값을 나타냅니다.
  • ptr += 3은 포인터를 3칸 이동시켜 네 번째 요소를 가리키도록 합니다.

 

3. 동적 메모리 할당: 예시로 능숙하게 다루기

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

int main() {
    int* ptr = (int*)malloc(5 * sizeof(int)); // 5개의 int형 변수를 저장할 메모리 할당

    if (ptr == NULL) {
        printf("메모리 할당 실패!\n");
        return 1;
    }

    for (int i = 0; i < 5; i++) {
        ptr[i] = i * 10;
    }

    for (int i = 0; i < 5; i++) {
        printf("%d ", ptr[i]); // 0 10 20 30 40
    }
    printf("\n");

    free(ptr); // 할당된 메모리 해제

    return 0;
}

 

 

  • malloc을 사용하여 5개의 int형 변수를 저장할 메모리를 할당하고, 그 시작 주소를 ptr에 저장합니다.
  • ptr을 배열처럼 사용하여 값을 저장하고 출력합니다.
  • free를 사용하여 할당된 메모리를 해제합니다

 

 

4. 고급 포인터 활용: 예시로 실력 향상

#include <stdio.h>

int add(int a, int b) {
    return a + b;
}

int subtract(int a, int b) {
    return a - b;
}

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

    func_ptr = add;
    printf("add(3, 5): %d\n", func_ptr(3, 5)); // 8

    func_ptr = subtract;
    printf("subtract(3, 5): %d\n", func_ptr(3, 5)); // -2

    return 0;
}

 

  • func_ptr은 두 개의 int형 인자를 받고 int형 값을 반환하는 함수의 주소를 저장하는 포인터입니다.
  • func_ptr에 add 함수와 subtract 함수의 주소를 각각 할당하고, 함수 포인터를 통해 함수를 호출합니다.
 
 

C 언어 포인터 완전 정복: 구조체와 함께 더 깊이 있는 이해! 

 

1. 구조체와 포인터: 데이터의 집합을 효율적으로 관리하기

  • 구조체: 관련된 여러 데이터를 하나로 묶어 새로운 자료형을 만드는 기능입니다.
  • 구조체 포인터: 구조체 변수의 주소를 저장하는 포인터입니다.
  • 접근 연산자:
    • . 연산자: 구조체 변수를 통해 멤버에 접근할 때 사용합니다. (예: student.name)
    • -> 연산자: 구조체 포인터를 통해 멤버에 접근할 때 사용합니다. (예: ptr->name)

2. 구조체 포인터: 예시로 쉽게 이해하기

#include <stdio.h>
#include <string.h>

struct Student {
    char name[20];
    int age;
    float grade;
};

int main() {
    struct Student student1 = {"Alice", 20, 3.8};
    struct Student* ptr = &student1; // student1의 주소를 ptr에 저장

    printf("student1.name: %s\n", student1.name); // Alice
    printf("ptr->name: %s\n", ptr->name); // Alice

    strcpy(ptr->name, "Bob"); // ptr을 통해 name 멤버 변경
    printf("student1.name 변경 후: %s\n", student1.name); // Bob

    return 0;
}

 

 

  • student1 구조체 변수를 선언하고 초기화합니다.
  • ptr 구조체 포인터를 선언하고 student1의 주소를 저장합니다.
  • . 연산자와 -> 연산자를 사용하여 구조체 멤버에 접근하고 값을 출력합니다.
  • ptr->name을 사용하여 구조체 멤버의 값을 변경합니다.

3. 동적 메모리 할당과 구조체: 유연한 메모리 관리

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

struct Student {
    char name[20];
    int age;
    float grade;
};

int main() {
    struct Student* ptr = (struct Student*)malloc(sizeof(struct Student));

    if (ptr == NULL) {
        printf("메모리 할당 실패!\n");
        return 1;
    }

    strcpy(ptr->name, "Charlie");
    ptr->age = 22;
    ptr->grade = 3.5;

    printf("ptr->name: %s, ptr->age: %d, ptr->grade: %.1f\n", 
           ptr->name, ptr->age, ptr->grade); // Charlie, 22, 3.5

    free(ptr);

    return 0;
}

 

 

  • malloc을 사용하여 구조체 크기만큼 메모리를 할당하고, 그 시작 주소를 ptr에 저장합니다.
  • ptr-> 연산자를 사용하여 구조체 멤버에 접근하고 값을 할당합니다.
  • free를 사용하여 할당된 메모리를 해제합니다.

4. 연결 리스트: 구조체와 포인터의 환상적인 조합

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

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

int main() {
    struct Node* head = NULL;
    struct Node* second = NULL;
    struct Node* third = NULL;

    head = (struct Node*)malloc(sizeof(struct Node));
    second =

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

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

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

    struct Node* current = head;
    while (current != NULL) {
        printf("%d ", current->data); // 1 2 3
        current = current->next;
    }
    printf("\n");

    free(third);
    free(second);
    free(head);

    return 0;
}

 

 

  • Node 구조체는 데이터와 다음 노드를 가리키는 포인터를 멤버로 가집니다.
  • 세 개의 노드를 동적으로 생성하고, 포인터를 이용하여 연결 리스트를 구성합니다.
  • while 루프를 사용하여 연결 리스트를 순회하며 데이터를 출력합니다.
  • 할당된 메모리를 해제합니다.

 

728x90
반응형

'개발 일지 > C언어' 카테고리의 다른 글

tolower 함수란?  (0) 2024.09.15
구조체란?  (0) 2024.08.23
strcpy 함수  (0) 2024.08.21
2024 08 04 개발일지 C언어 찍먹하기 2 (조건문)  (0) 2024.08.05
2024 08 03 개발일지 C언어 찍먹하기  (0) 2024.08.04
'개발 일지/C언어' 카테고리의 다른 글
  • tolower 함수란?
  • 구조체란?
  • strcpy 함수
  • 2024 08 04 개발일지 C언어 찍먹하기 2 (조건문)
DDD Developer
DDD Developer
  • DDD Developer
    DDD
    DDD Developer
  • 전체
    오늘
    어제
    • 분류 전체보기
      • 개발 일지
        • C언어
        • python 파이썬
        • 기타
        • 데이터베이스
        • TCP 와 IP
        • C++
        • QT
        • C#
      • 스터디
        • C언어
        • python 파이썬
        • TCP 와 IP
        • C++ 스터디
        • QT 스터디
      • 프로젝트
      • 문제풀이
        • C언어
        • python 파이썬
  • 인기 글

  • 최근 글

  • 반응형
  • hELLO· Designed By정상우.v4.10.2
DDD Developer
포인터란?
상단으로

티스토리툴바