[C/C++] sizeof 연산자와 컴파일 타임 평가

hwhyeons·2025년 8월 8일

sizeof는 타입 또는 표현식의 크기를 구하는 연산자다.

sizeof는 함수가 아니라 연산자다.


보통 sizeof는 아래와 같은 경우에 주로 사용 된다.

  • C언어에서 배열의 원소 개수를 구할 때
  • malloc등 동적 메모리 할당 시에 크기 결정


sizeof는 연산자 / 형태

sizeof는 함수가 아니라 단항 연산자다.

sizeof는 보통 sizeof(a) 이런 형식으로 괄호 안에 크기를 구하고 싶은
것을 넘기는 경우가 많기 때문에 함수처럼 보이지만, 함수가 아니다.
특히,

int a = 10;
int b = 10;
std::cout << sizeof(a+b);

이렇게 sizeof안에 타입이나 변수(상수)가 아닌
a+b와 같은 표현식이 올 수 있다보니 더 함수처럼 보여서 헷갈린다.

또한 sizeof는 sizeof(a)의 형태도 가능하지만
sizeof a와 같이 괄호 없이도 사용가능하다.

괄호를 쓰는 것과 안쓰는 방식은 동일하지만,
타입의 크기를 출력하고 싶을 때는 괄호를 사용해야한다
(ex : sizeof(int))



sizeof는 '컴파일 타임'에 계산되는 연산자

sizeof가 함수가 아니라 연산자라는 것도 중요하지만,
더 중요한 것은 sizeof는 컴파일 타임에 결정되는 연산자라는 것이다.

이 컴파일 타임에 결정된다는 부분 때문에 여러가지로 잘못된 사용이 될 수 있고,
또 사용이 안될 것 같은 부분에서 사용이 될 수도 있다.

또 컴파일 타임에 결정되는 것을 알고 있으면 여러가지로 sizeof의 연산 결과를 이해하는데도
도움이 크게 되는 것 같다.


알다시피 함수는 런타임에 호출된다.
아래와 같은 코드를 보자

int func() {
    std::cout << "called\n";
    return 42;
}

int main() {
    std::cout << sizeof(func());  // func()는 호출되지 않음. 컴파일 타임 평가
}

이 코드는 func()를 실행하지 않는다.

sizeof()가 만약에 일반 함수였다면, sizeof()를 실행하기 전에 func()를 먼저 실행했을 것이다.

그러면 위 결과는 어떻게 나올까?

바로 4가 출력되는데, 그 이유는 func()의 반환 타입의 크기를 리턴한다.


어떻게 func()를 실행도 안하는데 sizeof(func())는 판별이 가능할까?

sizeof는 컴파일타임에 평가된다고 했는데,
함수의 반환타입도 당연히 컴파일 타임에 무조건 결정할 수 있다.


이렇게 sizeof가 컴파일타임에 평가 된다는 것을 알고 있으면 sizeof의 연산 대상이
누가 와도 쉽게 이해할 수 있다.

다른 예시로 후위,전위 증감 연산이 온다고 해보자

int a = 10;
std::cout << sizeof(++a) << "\n";
std::cout << "실제 a값 : "<< a;

출력

4
실제 a값 : 10

마찬가지로 sizeof()는 이미 컴파일 타임에 판별되므로,
sizeof(++a)라는 것은 ++a를 실행하는 것이 아니라 ++a의 반환 타입의 크기를 출력하게 된다.

++a가 런타임에 실행되지 않고 sizeof(++a)는 이미 컴파일 시점에 결정되었기 때문에,
a는 10 그대로다.


컴파일 타임에 판별되는지를 확인하는 간단한 방법으로, 배열을 사용해보는 방법이 있다.

C++표준에서는 배열의 크기는 컴파일 타임에 결정 되어야한다.

예를들어

int a;
std::cin >> a;
int arr[a];

와 같은 코드는 컴파일이 안된다.
(단, GCC등 일부 컴파일러는 비표준 확장 기능으로 이 가변 길이 배열을 지원한다)
(위 코드가 오류가 없다면 컴파일러 flag에 -pedantic을 주면 ISO 표준을 따르게 되므로
컴파일이 막힌다)
(또한, C++이 아닌 C99 이후부터는 VLA(Variable Length Array)를 지원하기 때문에 C++이 아닌 C에서는 문제 없이 동작할 수 있으니 주의)

만약 sizeof가 컴파일 타임에 평가 된다면, 배열의 크기에 sizeof의 결과를 넣게 되면
오류가 없이 컴파일 될 것이다.

#include <iostream>
int main() {
    int a;
    std::cin >> a;
    int arr[sizeof(a)];
    std::cout << arr[1];
}

오류 없이 잘 된다.
sizeof의 결과가 int타입의 크기이므로 4가 될 것이고, 따라서 int타입 4개 크기의 배열이 생성될 것이다.
(위 코드는 실전에서 쓸데없는 코드이지만 컴파일 타임 판별성을 위해서 한번 테스트 해봤다)


sizeof는 정적 크기를 리턴한다.
따라서 동적할당된 메모리의 크기를 판별할 수는 없다.

sizeof가 컴파일 타임에 평가되는 것을 알면 동적할당된 메모리의 크기를 측정할 수 없다는 것도
자연스럽게 이해하고 암기할 수 있다.


sizeof의 피연산자로 표현식이 오더라도 컴파일 타임에 평가가 가능하다.

int a = 10;
double b;
std::cin >> b;
std::cout << sizeof(a+b);

결과는 8이다.
a+b의 결과 자체는 컴파일 타임에 절대 알 수 없지만,
a+b가 반환하는 결과의 타입은 double임이 자명하다.
따라서 sizeof(a+b)는 사칙연산 형변환에 의해 double이 되므로 8이 나옴을 알 수 있다.

0개의 댓글