C언어 초급 - 10장: 포인터 (10.2 포인터의 기본 연산)

2025. 2. 24. 11:43프로그래밍 언어/C

10.2 포인터의 기본 연산

C 언어에서 포인터(Pointer)변수의 메모리 주소를 저장하는 변수입니다.
포인터를 사용하면 메모리 주소를 직접 조작하고, 배열과 유사한 방식으로 데이터를 처리할 수 있습니다.
포인터의 기본 연산을 이해하면 배열, 함수, 동적 메모리 할당 등을 효과적으로 활용할 수 있습니다.


1. 포인터 변수 선언 및 초기화

1.1 포인터 변수 선언

포인터 변수는 특정 자료형을 가리킬 수 있도록 선언해야 합니다.

자료형 *포인터이름;

📌 포인터 변수의 자료형은 가리키는 변수의 자료형과 동일해야 합니다.

포인터 선언 설명
int *ptr; int 타입 변수를 가리키는 포인터
double *ptr; double 타입 변수를 가리키는 포인터
char *ptr; char 타입 변수를 가리키는 포인터

1.2 포인터 변수 초기화

포인터 변수를 선언한 후, 반드시 유효한 메모리 주소로 초기화해야 합니다.

#include <stdio.h>

int main() {
    int num = 10;
    int *ptr = &num;  // 포인터에 num의 주소 저장

    printf("num의 값: %d\n", num);
    printf("포인터 ptr이 가리키는 값: %d\n", *ptr);
    printf("포인터 ptr이 저장하는 주소: %p\n", ptr);

    return 0;
}

출력 결과

num의 값: 10
포인터 ptr이 가리키는 값: 10
포인터 ptr이 저장하는 주소: 0x7ffee3b3d9c0

📌 설명

  • int *ptr = &num; → ptr이 num의 주소를 저장.
  • *ptr → ptr이 가리키는 변수 num의 값을 가져옴.

2. 포인터 연산

포인터는 메모리 주소를 다루므로, 주소를 증가(++) 또는 감소(--)하여 메모리 공간을 이동할 수 있습니다.

2.1 포인터 증가(ptr++)

포인터를 증가시키면, 다음 메모리 위치로 이동합니다.

#include <stdio.h>

int main() {
    int num = 10;
    int *ptr = &num;

    printf("ptr의 주소: %p\n", ptr);
    ptr++;  // 포인터 증가 (다음 정수형 메모리 주소로 이동)
    printf("ptr 증가 후 주소: %p\n", ptr);

    return 0;
}

출력 예시

ptr의 주소: 0x7ffee3b3d9c0
ptr 증가 후 주소: 0x7ffee3b3d9c4

📌 설명

  • ptr++ → 다음 int 크기(4바이트)만큼 주소 증가.

2.2 포인터 감소(ptr--)

포인터를 감소시키면, 이전 메모리 위치로 이동합니다.

ptr--;  // 포인터 감소 (이전 메모리 주소로 이동)

📌 포인터 증가/감소 연산은 포인터의 자료형 크기에 따라 주소를 이동합니다.
예를 들어:

  • int 포인터(int *ptr) → 4바이트씩 이동
  • double 포인터(double *ptr) → 8바이트씩 이동
  • char 포인터(char *ptr) → 1바이트씩 이동

2.3 포인터 덧셈 (ptr + n)

포인터에 n을 더하면, n번째 요소의 주소로 이동합니다.

ptr = ptr + 2;  // ptr을 2개의 메모리 블록(정수형의 경우 8바이트) 앞으로 이동

2.4 포인터 뺄셈 (ptr - n)

포인터에서 n을 빼면, n번째 이전 요소의 주소로 이동합니다.

ptr = ptr - 1;  // ptr을 1개의 메모리 블록(정수형의 경우 4바이트) 뒤로 이동

3. 포인터와 배열의 관계

3.1 배열과 포인터의 연관성

배열과 포인터는 서로 밀접한 관계가 있습니다.
배열의 이름 자체가 배열의 첫 번째 요소의 주소를 의미합니다.

int arr[5] = {10, 20, 30, 40, 50};
  • arr 자체가 &arr[0]의 주소값과 동일.
  • 즉, arr는 포인터처럼 동작할 수 있음.

3.2 배열을 포인터로 접근하기

#include <stdio.h>

int main() {
    int arr[3] = {10, 20, 30};
    int *ptr = arr;  // 배열의 첫 번째 요소 주소 저장

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

    return 0;
}

출력 결과

arr[0]: 10, *ptr: 10
arr[1]: 20, *(ptr + 1): 20
arr[2]: 30, *(ptr + 2): 30

📌 설명

  • ptr = arr; → 배열의 첫 번째 요소의 주소를 저장.
  • *ptr → arr[0]의 값(10).
  • *(ptr + 1) → arr[1]의 값(20).
  • *(ptr + 2) → arr[2]의 값(30).

3.3 배열을 포인터 연산으로 순회하기

배열 요소를 포인터를 사용하여 반복문으로 순회할 수 있습니다.

#include <stdio.h>

int main() {
    int arr[5] = {1, 2, 3, 4, 5};
    int *ptr = arr;  // 배열의 첫 번째 요소 주소

    for (int i = 0; i < 5; i++) {
        printf("arr[%d] = %d\n", i, *(ptr + i));  // 포인터 연산으로 배열 요소 접근
    }

    return 0;
}

출력 결과

arr[0] = 1
arr[1] = 2
arr[2] = 3
arr[3] = 4
arr[4] = 5

📌 설명

  • ptr + i → arr[i]의 주소를 의미.
  • *(ptr + i) → 해당 주소의 값을 가져옴.

4. 정리

개념  설명  예제
포인터 선언 특정 자료형을 가리키는 포인터 선언 int *p;
포인터 초기화 특정 변수의 주소를 저장해야 함 int *p = &num;
주소 연산자(&) 변수의 메모리 주소를 반환 &num
포인터 연산자(*) 포인터가 가리키는 값에 접근 *ptr = 30;
포인터 증가/감소 다음 또는 이전 메모리 위치로 이동 ptr++, ptr--
포인터와 배열 배열의 이름은 첫 번째 요소의 주소 int *p = arr;
포인터로 배열 접근 포인터 연산으로 배열 요소에 접근 가능 *(ptr + i)

📌 배열의 이름은 포인터처럼 동작하며, 첫 번째 요소의 주소를 의미함
📌 포인터 연산(ptr + n, ptr++)을 이용해 배열 요소에 접근 가능
📌 배열을 포인터로 순회하면 더 효율적으로 데이터 조작 가능