Computer >> 컴퓨터 >  >> 프로그래밍 >> C 프로그래밍

C/C++에서 배열이 함수로 전달되는 방식 – 포인터로 변환되는 이유

개요

이 글에서는 C/C++ 프로그램에서 배열이 함수에 어떻게 전달되는지 살펴봅니다. 결론부터 말하면, C/C++에서 배열을 함수 인자로 넘기면 배열 전체가 복사되는 것이 아니라 배열의 첫 번째 요소를 가리키는 포인터(pointer) 형태로 전달됩니다. 이러한 현상을 흔히 '배열의 감쇠(array decay)'라고 부릅니다.

배열이 포인터로 전달되는 이유

배열 전체를 값으로 복사하면 메모리 사용량과 성능 면에서 비효율적일 수 있습니다. 그래서 C 언어 설계 당시부터 배열 이름은 대부분의 표현식에서 첫 번째 요소를 가리키는 포인터로 암묵적으로 변환되며, 함수 호출 시에도 마찬가지로 포인터만 전달됩니다. 따라서 함수 내부에서는 원본 배열의 실제 크기를 알 방법이 없습니다.

예제 코드

#include <stdio.h>

// 배열을 포인터 형태로 전달받는 함수
void fun(int arr[]) {
    unsigned int n = sizeof(arr) / sizeof(arr[0]);
    printf("\nfun() 내부의 배열 크기: %d", n);
}

int main() {
    int arr[] = {1, 2, 3, 4, 5, 6, 7, 8};
    unsigned int n = sizeof(arr) / sizeof(arr[0]);
    printf("main() 내부의 배열 크기: %d", n);
    fun(arr);
    return 0;
}

실행 결과

main() 내부의 배열 크기: 8
fun() 내부의 배열 크기: 2

결과 분석

같은 배열을 다루는데 두 함수의 출력이 서로 다른 이유는 다음과 같습니다.

  • main() 안에서: arr은 여전히 배열이므로 sizeof(arr)는 배열 전체 크기인 32바이트(8개 × 4바이트)를 반환합니다. 여기에 요소 하나의 크기인 4바이트를 나누면 8이 계산됩니다.
  • fun() 안에서: 매개변수 arr은 사실상 int* 포인터입니다. 따라서 sizeof(arr)는 포인터 크기인 8바이트(64비트 시스템 기준)를 반환하고, 8 ÷ 4 = 2가 출력됩니다.

올바른 해결 방법

함수 내부에서 배열의 크기가 필요하다면, 배열과 함께 크기를 별도의 매개변수로 전달하는 것이 표준적인 방법입니다.

void fun(int arr[], unsigned int n) {
    printf("배열 크기: %u\n", n);
}

int main() {
    int arr[] = {1, 2, 3, 4, 5, 6, 7, 8};
    unsigned int n = sizeof(arr) / sizeof(arr[0]);
    fun(arr, n); // 크기 정보를 함께 전달
    return 0;
}

이처럼 C/C++에서 배열을 함수에 전달하면 항상 포인터로 변환된다는 점을 기억하고, 필요한 경우 크기 정보를 함께 넘겨주는 습관을 들이는 것이 안전한 코드 작성의 기본입니다.