C 기본 문법 – 포인터 – 2 – 포인터와 함수

C 기본 문법 – 포인터 – 2편: 포인터와 함수 완전 정복

안녕하세요, 여러분! 😊
오늘은 C 언어에서 포인터와 함수가 어떻게 짝꿍처럼 함께 동작하는지를 알아볼 시간이에요.

🧠 함수는 기본적으로 **값을 복사해서 전달(call by value)**하기 때문에,
함수 안에서 변수의 값을 변경해도 원본에는 영향을 주지 않아요!
그런데 포인터를 사용하면 원본 데이터를 직접 수정할 수 있답니다.

이건 마치 복사본이 아닌 실제 문서를 직접 수정하는 것과 같아요!
그럼 실전 예제와 함께 포인터와 함수의 환상적인 콤비를 배워볼까요? 😄


1. 함수 인자 전달 방식

기본 전달 방식: 값에 의한 전달 (Call by Value)

void change(int a) {
    a = 100;
}

int main() {
    int x = 10;
    change(x);
    printf("%d
", x);  // 출력: 10
}

🧾 x의 복사본이 a로 전달되기 때문에 원본 x는 변하지 않아요.


2. 포인터를 이용한 전달: 주소에 의한 전달 (Call by Reference)

void change(int *a) {
    *a = 100;
}

int main() {
    int x = 10;
    change(&x);
    printf("%d
", x);  // 출력: 100
}

✅ 포인터로 전달하면 원본 값을 직접 수정할 수 있어요!


3. 함수에서 여러 값 반환하기

C는 return 하나밖에 못하죠? 그런데 포인터를 사용하면 여러 값을 반환하는 효과를 낼 수 있어요!

예시: 두 수를 더하고 곱한 결과를 반환

void calc(int a, int b, int *sum, int *prod) {
    *sum = a + b;
    *prod = a * b;
}

int main() {
    int s, p;
    calc(3, 4, &s, &p);
    printf("합: %d, 곱: %d
", s, p);  // 출력: 합: 7, 곱: 12
}

🎯 포인터를 사용하면 여러 개의 “결과 출력구”를 만들 수 있답니다!


4. 배열을 함수에 전달할 때

배열을 함수에 넘기면 자동으로 포인터처럼 동작해요.

void printArr(int *arr, int len) {
    for (int i = 0; i < len; i++)
        printf("%d ", arr[i]);
}

int main() {
    int nums[4] = {1, 2, 3, 4};
    printArr(nums, 4);
}

💡 배열은 항상 첫 번째 요소의 주소로 전달되므로 포인터 매개변수로 받습니다!


5. 문자열 함수도 결국 포인터 기반!

void printStr(char *str) {
    while (*str) {
        printf("%c", *str);
        str++;
    }
    printf("
");
}

int main() {
    char msg[] = "Hello!";
    printStr(msg);
}

문자열은 문자 배열이므로 자연스럽게 포인터와 함께 쓰이는 구조에요 😊


6. 포인터를 반환하는 함수

함수에서 포인터를 반환할 수도 있어요!
하지만 지역 변수의 주소를 반환하면 위험하니 주의하세요!

❌ 위험한 예시

int* getAddress() {
    int temp = 10;
    return &temp;  // 이 주소는 함수 끝나면 사라짐!
}

✅ 안전한 예시 (동적 메모리)

int* createArray(int n) {
    return (int *)malloc(sizeof(int) * n);
}

📌 함수에서 malloc으로 메모리 할당한 뒤 포인터 반환하면 안전해요!


7. 함수 포인터 (심화 개념 맛보기)

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

int main() {
    int (*func)(int, int) = add;
    printf("%d
", func(3, 5));  // 결과: 8
}

🎯 함수도 주소를 가질 수 있고, 포인터로 호출할 수 있어요!
이건 나중에 콜백 함수나 동적 호출에서 자주 쓰이니 살짝 기억만 해두세요 😊


✅ 포인터와 함수 요약 정리

패턴 설명 예시
포인터로 값 수정 주소 전달 후 *로 값 변경 change(&x);
배열 전달 자동으로 포인터처럼 전달 printArr(arr, len);
여러 값 반환 포인터 매개변수 여러 개 calc(a, b, &sum, &prod);
포인터 반환 malloc 등으로 메모리 생성 return malloc(...);
함수 포인터 함수 주소 저장 후 호출 (*func)(x, y);

⚠️ 포인터와 함수 사용 시 주의사항

주의점 설명
지역 변수 주소 반환 금지 함수 종료 후 사라지는 주소 반환은 위험
포인터 초기화 NULL 또는 유효한 주소로 초기화 후 사용
배열 크기 명시 포인터로 배열 받는 경우 크기 따로 전달
메모리 해제 malloc으로 받은 포인터는 반드시 free()
*& 헷갈림 주의 *는 값, &는 주소입니다!

마무리하며 💬

포인터와 함수의 조합은 함수로 데이터를 유연하게 처리하고 조작할 수 있는 강력한 무기예요!
포인터 없이 함수만 써서는 절대 할 수 없는 일들이 정말 많죠.

🎯 포인터는 “실물 주소를 들고 직접 찾아가는 메신저”,
함수는 “그 메신저에게 일을 시키는 명령 센터” 같아요.

이제 포인터와 함수가 어떻게 소통하는지 잘 이해되셨죠?
다음 시간에는 더 심화된 내용인 함수 포인터와 콜백 함수 등에 대해 다뤄볼게요!

질문이 있다면 언제든지 남겨주세요!
우리 함께 C 마스터 되자구요 💪😄

답글 남기기