C++에서 sizeof 이해하기: 왜 n8이 아닌가?

C++에서 배열을 다룰 때, 특히 배열을 함수에 전달할 때 sizeof 연산자와 관련된 예상치 못한 결과를 마주칠 수 있습니다. 이 블로그 포스트에서는 sizeof를 함수 매개변수와 함께 사용할 때 발생하는 일반적인 혼란, 특히 **왜 함수 foo()에서 n8이 아닌가?**라는 질문에 대해 탐구해 보겠습니다.

문제

아래 두 개의 코드를 살펴보면서 문제를 설명하겠습니다:

예제 1: 함수 foo()

void foo(char cvalue[8])
{
    int n = sizeof(cvalue);
}

위의 예제에서 sizeof(cvalue)를 호출할 때, 배열의 크기가 8로 정의되어 있으므로 n8일 것이라고 생각할 수 있습니다. 그러나 이 경우는 그렇지 않습니다.

예제 2: 함수 bar()

void bar()
{
    char cvalue[8];
    int n = sizeof(cvalue);
}

두 번째 예제에서는 sizeof(cvalue)가 실제로 8과 같습니다. 그렇다면 왜 차이가 있을까요?

개념 이해하기

왜 각 함수에서 sizeof(cvalue)가 다른 값을 반환하는지 이해하려면 C와 C++에서 배열이 어떻게 처리되는지 명확히 해야 합니다.

배열을 함수 매개변수로 사용하기

C나 C++에서 배열을 함수에 전달할 때, 실제로 배열 자체를 전달하는 것이 아닙니다. 대신 배열의 첫 번째 요소에 대한 포인터를 전달하는 것입니다. 함수 매개변수에서 사용되는 괄호는 단순히 문법적 표기일 뿐이며, 동작에 변화를 주지 않습니다. 다음 두 선언은 모두 동등합니다:

  • void foo(char cvalue[8])
  • void foo(char cvalue[])
  • void foo(char *cvalue)

이 모든 선언에서 cvalue는 포인터로 해석됩니다. 따라서 foo() 안에서 sizeof(cvalue)를 호출하면, 배열의 크기가 아니라 포인터의 크기가 반환됩니다. 대부분의 플랫폼에서 이 크기는 32비트 시스템에서 일반적으로 4 바이트, 64비트 시스템에서 8 바이트입니다. 그래서 foo()에서 n8이 아닌 것입니다.

bar()에서의 올바른 컨텍스트

반면, bar() 안에서 cvalue는 크기 8인 지역 배열로 정의됩니다. 따라서 여기서 sizeof(cvalue)가 호출될 때, 전체 배열의 크기를 정확히 반영하여 n8이 됩니다.

주요 요점

  • 포인터 동작 이해하기: 배열을 매개변수로 전달할 때, 실제로는 포인터를 전달하는 것이므로 sizeof를 사용할 때 혼란스러운 값을 초래할 수 있습니다.
  • 지역 배열: sizeof는 함수 내에서 정의된 지역 배열의 실제 크기를 제공합니다.
  • 문법적 설탕: 함수 매개변수의 괄호는 배열 변수를 생성하는 것이 아니라 포인터를 다룬다는 것을 나타냅니다.

결론

C와 C++에서 배열을 처리하는 것은 언어에 익숙하지 않은 사람들에게는 까다로울 수 있습니다. 포인터와 배열의 차이를 이해하는 것은 정확한 계산과 디버깅을 위해 매우 중요합니다. 함수 내에서 배열로 간주되는 매개변수에 sizeof를 적용하면 배열이 아니라 포인터의 크기를 반환한다는 점을 기억하세요.

이 설명이 함수의 배열 인자와 관련하여 sizeof 연산자의 동작을 명확히 이해하는 데 도움이 되기를 바랍니다. foo()에서 n8이 아닌 이유와 bar()에서 왜 8인지의 차이를 설명했습니다. 코딩할 때 이러한 원칙을 기억하세요!