C언어 공부

C언어 기초 - 8-1. 포인터의 개념 연습문제

Client Side 2025. 8. 15. 16:24

 

문제 1. 기본 포인터 선언 및 역참조

num이라는 int 변수를 선언하고 10으로 초기화한다. 그 다음 ptr이라는 int 포인터를 선언하여 num의 주소를 저장한다. ptr을 이용하여 num의 값을 20으로 변경한다. 마지막으로 num과 *ptr의 값을 각각 출력한다.

c

#include <stdio.h>

int main()
{
    int num = 10;
    int* ptr = &num;
    *ptr = 20;
    printf("num의 값: %d\n", num);
    printf("*ptr의 값: %d\n", *ptr);
    return 0;
}

해설: int num = 10;은 정수형 변수 num을 선언하고 초기값 10을 할당하는 문장이다. int* ptr = &num;은 int형 포인터 ptr을 선언하고, &num을 통해 num 변수의 메모리 주소를 ptr에 할당하는 문장이다. 즉, ptr은 num이 저장된 메모리 공간을 가리키게 된다. *ptr = 20;은 ptr이 가리키는 메모리 위치(여기서는 num 변수의 위치)에 저장된 값을 20으로 변경하는 역참조 연산이다. 이로 인해 num 변수의 값은 10에서 20으로 변경된다. printf("%d\n", num);은 num 변수의 현재 값인 20을 출력한다. printf("%d\n", *ptr);은 ptr이 가리키는 위치의 값, 즉 num의 값인 20을 출력한다. 이는 num 변수에 직접 접근하는 것과 동일한 결과를 가져온다.


문제 3. 포인터를 이용한 값 교환 (Swap)

a = 5, b = 10이라는 두 개의 int 변수를 선언하고 초기화한다. swap이라는 함수를 만드는데, 이 함수는 두 개의 int 포인터를 인자로 받아서, 그 포인터가 가리키는 두 변수의 값을 서로 바꿔주도록 구현한다. main 함수에서 a와 b를 선언하고, swap 함수를 호출하여 a와 b의 값을 교환한 후, main 함수에서 교환된 a와 b의 값을 출력한다.

c

#include <stdio.h>

// swap 함수 정의: 두 정수 포인터를 받아 그 값을 교환한다.
void swap(int* p, int* q)
{
    int temp = *p; // p가 가리키는 값을 임시 변수 temp에 저장한다.
    *p = *q;       // q가 가리키는 값을 p가 가리키는 곳에 저장한다.
    *q = temp;     // temp에 저장된 원래 p의 값을 q가 가리키는 곳에 저장한다.
}

int main()
{
    int a = 5; // 정수형 변수 a를 선언하고 5로 초기화한다.
    int b = 10; // 정수형 변수 b를 선언하고 10으로 초기화한다.

    printf("swap 함수 호출 전: a = %d, b = %d\n", a, b); // swap 함수 호출 전 값을 출력한다.

    // swap 함수 호출: 변수 a와 b의 주소를 인자로 전달한다.
    swap(&a, &b); // Call by Reference 방식으로, 함수 내에서 원본 변수의 값을 변경한다.

    printf("swap 함수 호출 후: a = %d, b = %d\n", a, b); // swap 함수 호출 후 변경된 값을 출력한다.
    return 0;
}

해설: void swap(int* p, int* q)는 두 개의 int형 포인터 p와 q를 인자로 받는 함수이다. 이 함수는 포인터가 가리키는 원본 변수의 값을 직접 변경하기 위해 사용된다. 이를 'Call by Reference'라고 한다. 함수 내부에서 int temp = *p;는 p가 가리키는 값(원본 a의 값)을 temp 변수에 임시로 저장한다. *p = *q;는 q가 가리키는 값(원본 b의 값)을 p가 가리키는 곳(원본 a의 위치)에 덮어쓴다. *q = temp;는 temp에 저장해 두었던 p의 원래 값을 q가 가리키는 곳(원본 b의 위치)에 덮어쓴다. 이 과정을 통해 두 변수의 값이 서로 교환된다. main 함수에서 swap(&a, &b);와 같이 & 연산자를 사용하여 변수 a와 b의 '주소'를 swap 함수에 전달하는 것이 핵심이다. 이렇게 주소를 넘겨야 함수 내부에서 포인터를 통해 원본 변수의 값에 접근하고 변경할 수 있다.


문제 4. NULL 포인터 확인

int_ptr이라는 int 포인터를 선언하고 NULL로 초기화한다. if문을 사용하여 int_ptr이 NULL인지 아닌지 확인하고, 만약 NULL이라면 "포인터가 NULL입니다."라고 출력한다. NULL이 아니라면 "포인터가 유효합니다."라고 출력한다.

c

#include <stdio.h>

int main()
{
    int* int_ptr = NULL; // int_ptr을 NULL로 초기화합니다. 할당 연산자 '='를 사용합니다.

    if (int_ptr == NULL) // int_ptr이 NULL인지 확인합니다. 비교 연산자 '=='를 사용합니다.
    {
        printf("포인터가 NULL입니다.\n");
    }
    else
    {
        printf("포인터가 유효합니다.\n");
    }
    return 0;
}

해설: int* int_ptr = NULL;은 int형 포인터 int_ptr을 선언하고 NULL 값으로 초기화하는 문장이다. 포인터 선언 시 int*는 포인터가 int형 데이터를 가리킴을 의미하고, =는 할당 연산자로 int_ptr에 NULL 값을 부여한다. NULL은 포인터가 어떠한 유효한 메모리 주소도 가리키지 않음을 명시적으로 나타내는 특별한 값이다. if (int_ptr == NULL) 조건문은 int_ptr 포인터가 NULL 값을 가지는지 여부를 판단한다. 여기서 ==는 비교 연산자이다. 포인터가 NULL인지 확인하는 것은, 포인터를 사용하기 전에 유효한 메모리 주소를 할당받았는지 검사하여 프로그램의 비정상적인 종료나 오류를 방지하는 중요한 안전 장치이다. 이 코드는 int_ptr이 NULL로 초기화되었으므로 조건문이 참이 되어 "포인터가 NULL입니다."라는 문장이 출력된다.


문제 5. 이중 포인터 (Pointer to Pointer)

value라는 int 변수를 선언하고 100으로 초기화한다. ptr1이라는 int 포인터를 선언하여 value의 주소를 가리키게 한다. 마지막으로 ptr2라는 **이중 포인터 (int**)를 선언하여 ptr1의 주소를 가리키게 한다. ptr2를 사용하여 최종적으로 value의 값을 출력하는 코드를 작성한다.

c

#include <stdio.h>

int main()
{
    int value = 100;     // 정수형 변수 value를 선언하고 100으로 초기화합니다.
    int* ptr1 = &value;  // int형 포인터 ptr1을 선언하고 value의 주소를 저장합니다.
    int** ptr2 = &ptr1;  // int형 이중 포인터 ptr2를 선언하고 ptr1의 주소를 저장합니다.

    // 이중 포인터 ptr2를 통해 value의 값에 접근합니다.
    // *ptr2는 ptr1의 값을 가져오고 (즉, value의 주소),
    // **ptr2는 그 주소가 가리키는 값 (value의 값)을 가져옵니다.
    printf("value의 값: %d\n", **ptr2);
    return 0;
}

해설: int value = 100;은 정수형 변수 value를 선언하고 100을 할당하는 문장이다. int* ptr1 = &value;는 int형 포인터 ptr1을 선언하고 value 변수의 메모리 주소를 저장한다. 이로써 ptr1은 value를 직접 가리키게 된다. ptr1의 타입은 int*이다. int** ptr2 = &ptr1;은 int형 이중 포인터 ptr2를 선언하고 ptr1 포인터 변수 자체의 메모리 주소를 저장한다. ptr1의 주소를 저장하므로 ptr2의 타입은 int*를 가리키는 int**가 되어야 한다. ptr2는 ptr1을 가리키고, ptr1은 다시 value를 가리키는 형태이다. printf("value의 값: %d\n", **ptr2);는 이중 포인터 ptr2를 사용하여 최종적으로 value의 값에 접근하여 출력한다. *ptr2는 ptr2가 가리키는 대상인 ptr1의 값(즉, value의 주소)을 의미한다. 여기에 다시 * 연산을 적용하면 ptr1이 가리키는 대상인 value의 값(100)에 접근하게 된다. 따라서 100이 출력된다.