[C언어 스터디 - 12] 포인터를 입력으로 이용하는 함수 (function using pointers as inputs)

2020. 7. 2. 11:0003. Resources/C, C++

728x90
반응형

C언어 함수 정리

참고 문헌 (Ch 63): https://dojang.io/mod/page/view.php?id=549

포인터 매개변수 사용하기

일반적인 자료형을 이용했을 때의 결과

#include <stdio.h>

void swapNumber(int first, int second)    // 반환값 없음, int형 매개변수 두 개 지정
{
    int temp;    // 임시 보관 변수

    temp = first;
    first = second;
    second = temp;
}

int main()
{
    int num1 = 10;
    int num2 = 20;

    swapNumber(num1, num2);    // 변수 num1과 num2를 넣어줌

    printf("%d %d\n", num1, num2);    // 10 20: swapNumber 함수와는 상관없이 
                                      // 처음 저장한 10과 20이 출력됨

    return 0;
}

반환형이 void이기 때문에, 두 변수를 받아서 처리하더라도 아무런 변화가 나타나지 않는다.
매개변수를 포인터로 이용해야 해당 주소값에 있는 변수에 직접 접근해서 값을 바꿀 수 있다.

반환값자료형 함수이름(자료형 *매개변수1, 자료형 *매개변수2)
{
}

예시

#include <stdio.h>

void swapNumber(int *first, int *second)    // 반환값 없음, int 포인터 매개변수 두 개 지정
{
    int temp;    // 임시 보관 변수

    // 역참조로 값을 가져오고, 값을 저장함
    temp = *first;
    *first = *second;
    *second = temp;
}

int main()
{
    int num1 = 10;
    int num2 = 20;

    swapNumber(&num1, &num2);        // &를 사용하여 num1과 num2의 메모리 주소를 넣어줌

    printf("%d %d\n", num1, num2);   // 20 10: swapNumber에 의해서 num1과 num2의 값이 서로 바뀜

    return 0;
}

매개변수 포인터의 처리를 이해하기 쉽게 하는 방법

매개변수에서 처리할 포인터를 받아오는 경우, 입력과 출력에 대한 표시를 해주는 경우가 있다.

#define IN
#define OUT

//            ↓ 일반적인 매개변수
void GetValue(IN int a, OUT int *b)
{ //                     ↑ 값이 바깥으로 나오는 매개변수
    printf("%d\n", a);

    *b = 10;
}

IN과 OUT 표시는 컴파일 할 때 아무런 영향을 주지 않는 매크로가 된다. 사람만 알아볼 수 있는 부분

void 포인터 매개변수 사용하기

void 포인터 매개변수를 이용하면, 자료형 변환을 하지 않아도 모든 자료형을 함수에 넣을 수 있다.

#include <stdio.h>

enum TYPE {
    TYPE_CHAR,
    TYPE_INT,
    TYPE_FLOAT
};

void swapValue(void *ptr1, void *ptr2, enum TYPE t)    // 반환값 없음, void 포인터 매개변수 두 개와
{                                                      // 변수의 자료형을 알려줄 열거형을 받음
    switch (t)
    {
        case TYPE_CHAR:    // 문자면 char *로 변환한 뒤 역참조하여 값을 서로 바꿈
        {
            char temp;
            temp = *(char *)ptr1;
            *(char *)ptr1 = *(char *)ptr2;
            *(char *)ptr2 = temp;
            break;
        }
        case TYPE_INT:     // 정수면 int *로 변환한 뒤 역참조하여 값을 서로 바꿈
        {
            int temp;
            temp = *(int *)ptr1;
            *(int *)ptr1 = *(int *)ptr2;
            *(int *)ptr2 = temp;
            break;
        }
        case TYPE_FLOAT:    // 실수면 float *로 변환한 뒤 역참조하여 값을 서로 바꿈
        {
            float temp;
            temp = *(float *)ptr1;
            *(float *)ptr1 = *(float *)ptr2;
            *(float *)ptr2 = temp;
            break;
        }
    }
}

int main()
{
    char c1 = 'a';
    char c2 = 'b';
    swapValue(&c1, &c2, TYPE_CHAR);       // 변수의 메모리 주소와 TYPE_CHAR를 넣음
    printf("%c %c\n", c1, c2);            // b a: swapValue에 의해서 값이 서로 바뀜

    int num1 = 10;
    int num2 = 20;
    swapValue(&num1, &num2, TYPE_INT);   // 변수의 메모리 주소와 TYPE_INT를 넣음
    printf("%d %d\n", num1, num2);       // 20 10: swapValue에 의해서 값이 서로 바뀜

    float num3 = 1.234567f;
    float num4 = 7.654321f;
    swapValue(&num3, &num4, TYPE_FLOAT);  // 변수의 메모리 주소와 TYPE_FLOAT를 넣음
    printf("%f %f\n", num3, num4);        // 7.654321f 1.234567: 
                                          // swapValue에 의해서 값이 서로 바뀜

    return 0;
}

이중 포인터 매개변수 사용하기

포인터 매개변수를 이용해서 정수, 실수 등의 값 대신 포인터(메모리 주소)를 얻어오기 위한 방법이 필요!

#include <stdio.h>
#include <stdlib.h>    // malloc, free 함수가 선언된 헤더 파일

void allocMemory(void *ptr, int size)    // 반환값 없음, void 포인터 매개변수 지정
{
    ptr = malloc(size);    // ptr은 allocMemory를 벗어나면 사용할 수 없음
}

int main()
{
    long long *numPtr = NULL;

    // numPtr과 할당할 크기를 넣어줌 
    allocMemory(numPtr, sizeof(long long));

    *numPtr = 10;    // 메모리가 할당되지 않았으므로 실행 에러
    printf("%lld\n", *numPtr);

    free(numPtr);

    return 0;
}

디버그 포인트로 찍어보니, 선언한 값에 내용물이 아무것도 들어있지 않다. 이를 해결하기 위해서 이중 포인터를 이용.

#include <stdio.h>
#include <stdlib.h>    // malloc, free 함수가 선언된 헤더 파일

void allocMemory(void **ptr, int size)    // 반환값 없음, void 이중 포인터 매개변수 지정
{
    *ptr = malloc(size);    // void **ptr을 역참조하여 void *ptr에 메모리 할당
}

int main()
{
    long long *numPtr;

    // 단일 포인터 long long *numPtr의 메모리 주소는 long long **와 같음, 할당할 크기도 넣음 
    allocMemory(&numPtr, sizeof(long long));

    *numPtr = 10;
    printf("%lld\n", *numPtr);

    free(numPtr);    // 동적 메모리 해제

    return 0;
}

이렇게 하면 값이 되게 잘나온다. 이해가 잘 안되니까 보면서 좀 더 생각해보기


문자열 매개변수 사용하기

매개변수로 문자열을 받을 땐 매개변수를 문자열 포인터로 지정! 여러가지 형태로 문자열 입력을 지정할 수 있다.

char 포인터 매개변수 1개로 이용

#include <stdio.h>

void helloString(char *s1)    // 반환값 없음, char 포인터 매개변수 한 개 지정
{
    printf("Hello, %s\n", s1);    // Hello, 와 매개변수를 조합하여 문자열 출력
}

int main()
{
    helloString("world!");    // Hello, world!: 함수를 호출할 때 문자열을 전달

    return 0;
}

베열 형태의 문자열도 전달할 수 있음

#include <stdio.h>

void helloString(char *s1)    // 반환값 없음, char 포인터 매개변수 한 개 지정
{
    printf("Hello, %s\n", s1);    // Hello, 와 매개변수를 조합하여 문자열 출력
}

int main()
{
    char s1[10] = "world!";    // 배열 형태의 문자열

    helloString(s1);    // Hello, world!: 함수를 호출할 때 배열 전달

    return 0;
}

매개변수 뒤에 []를 붙여서 설정, 이 때 크기는 생략!

#include <stdio.h>

void helloString(char s1[])    // 반환값 없음, char 배열을 매개변수로 지정, 크기 생략
{
    printf("Hello, %s\n", s1);    // Hello, 와 매개변수를 조합하여 문자열 출력
}

int main()
{
    char s1[10] = "world!";   // 배열 형태의 문자열

    helloString(s1);          // Hello, world!: 함수를 호출할 때 배열 전달
    helloString("world!");    // Hello, world!: 함수를 호출할 때 문자열 전달

    return 0;
}
반응형