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

[C #12] 포인터 (Pointers)

by rnasterofmysea 2024. 12. 10.
반응형

포인터 (Pointers)

 

요약

  1. 포인터는 메모리 주소를 저장하며, 간접적으로 데이터를 조작.
  2. 배열과 포인터:
    • 배열 이름은 첫 번째 요소의 주소를 가리키는 포인터.
    • arr[i]는 *(arr + i)와 동일.
  3. 함수 포인터:
    • 함수를 가리키는 포인터로, 동적 함수 호출 가능.
  4. 동적 메모리와 포인터:
    • malloc, calloc, realloc, free를 통해 메모리를 동적으로 관리.
    •  

11.1 포인터의 개념

  • **포인터(pointer)**는 다른 변수의 메모리 주소를 저장하는 변수입니다.
  • **주소 연산자 (&)**와 **역참조 연산자 (*)**를 통해 값을 다룹니다.

포인터의 선언

데이터타입 *포인터이름;

예제

#include <stdio.h>

int main(void) {
    int x = 10;
    int *p;        // 정수를 가리키는 포인터 선언
    p = &x;        // x의 주소를 p에 저장

    printf("x의 값: %d\n", x);
    printf("x의 주소: %p\n", &x);
    printf("p의 값 (x의 주소): %p\n", p);
    printf("*p의 값 (x의 값): %d\n", *p);

    return 0;
}

출력 결과:

x의 값: 10
x의 주소: 0x7ffee4c0a9cc
p의 값 (x의 주소): 0x7ffee4c0a9cc
*p의 값 (x의 값): 10

11.2 포인터와 메모리 주소

1) 주소 연산자 (&)

  • 변수의 메모리 주소를 반환.
int x = 10;
int *p = &x;  // p에 x의 주소 저장

2) 역참조 연산자 (*)

  • 포인터가 가리키는 주소에 저장된 값을 참조하거나 수정.
int x = 10;
int *p = &x;

*p = 20;      // x의 값을 20으로 변경
printf("%d\n", x);  // 출력: 20

11.3 포인터와 함수

포인터를 함수의 매개변수로 전달하면, 함수 내부에서 원래 변수의 값을 변경할 수 있습니다.

포인터를 사용한 값 변경

#include <stdio.h>

void updateValue(int *p) {
    *p = 20;  // 포인터가 가리키는 변수의 값을 변경
}

int main(void) {
    int x = 10;

    printf("변경 전: %d\n", x);
    updateValue(&x);  // x의 주소 전달
    printf("변경 후: %d\n", x);

    return 0;
}

출력 결과:

변경 전: 10
변경 후: 20

11.4 배열과 포인터

배열의 이름은 배열의 첫 번째 요소의 주소를 나타내는 포인터처럼 작동합니다.

배열과 포인터의 관계

int arr[3] = {10, 20, 30};
printf("%p\n", arr);         // 배열의 시작 주소
printf("%p\n", &arr[0]);     // 첫 번째 요소의 주소

배열 요소 접근

  • arr[i]는 *(arr + i)와 동일합니다.
int arr[3] = {10, 20, 30};
printf("%d\n", arr[1]);      // 20
printf("%d\n", *(arr + 1));  // 20

11.5 포인터 산술 연산

포인터는 배열과 함께 사용할 때 산술 연산을 지원합니다.

포인터 증가

  • 포인터를 증가시키면, 데이터 타입 크기만큼 이동.
#include <stdio.h>

int main(void) {
    int arr[3] = {10, 20, 30};
    int *p = arr;

    printf("%d\n", *p);  // 10
    p++;
    printf("%d\n", *p);  // 20

    return 0;
}

11.6 다차원 배열과 포인터

1) 2차원 배열

2차원 배열은 배열의 배열로 표현됩니다.

  • matrix[i][j]는 *(*(matrix + i) + j)와 동일.
#include <stdio.h>

int main(void) {
    int matrix[2][3] = {{1, 2, 3}, {4, 5, 6}};

    printf("%d\n", matrix[1][2]);      // 6
    printf("%d\n", *(*(matrix + 1) + 2));  // 6

    return 0;
}

11.7 함수 포인터

1) 함수 포인터의 선언

  • 함수 포인터는 함수의 주소를 저장하는 포인터입니다.
반환형 (*포인터이름)(매개변수 타입들);

2) 함수 포인터 사용

#include <stdio.h>

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

int main(void) {
    int (*funcPtr)(int, int) = add;  // add 함수의 주소 저장

    printf("결과: %d\n", funcPtr(10, 20));  // 함수 호출

    return 0;
}

출력 결과:

결과: 30

11.8 동적 메모리 할당과 포인터

동적 메모리 할당은 포인터를 통해 관리됩니다.

1) 동적 메모리 할당 (malloc)

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

int main(void) {
    int *p = (int *)malloc(5 * sizeof(int));  // 정수 5개 메모리 할당

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

    for (int i = 0; i < 5; i++) {
        p[i] = i + 1;  // 메모리 초기화
    }

    for (int i = 0; i < 5; i++) {
        printf("%d ", p[i]);  // 출력
    }

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

출력 결과:

1 2 3 4 5

11.9 심화 예제

1) 포인터 배열

포인터 배열은 여러 포인터를 저장하는 배열입니다.

#include <stdio.h>

int main(void) {
    char *fruits[] = {"Apple", "Banana", "Cherry"};

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

    return 0;
}

출력 결과:

Apple
Banana
Cherry

2) 배열 포인터

배열 포인터는 배열 전체를 가리킵니다.

#include <stdio.h>

int main(void) {
    int arr[3] = {10, 20, 30};
    int (*p)[3] = &arr;

    printf("%d\n", (*p)[0]);  // 10
    printf("%d\n", (*p)[1]);  // 20

    return 0;
}

요약

  1. 포인터는 메모리 주소를 저장하며, 간접적으로 데이터를 조작.
  2. 배열과 포인터:
    • 배열 이름은 첫 번째 요소의 주소를 가리키는 포인터.
    • arr[i]는 *(arr + i)와 동일.
  3. 함수 포인터:
    • 함수를 가리키는 포인터로, 동적 함수 호출 가능.
  4. 동적 메모리와 포인터:
    • malloc, calloc, realloc, free를 통해 메모리를 동적으로 관리.
반응형