`sizeof` 연산자(sizeof operator)

sizeof 연산자(sizeof operator)

객체나 타입의 실제 크기를 바이트 단위로 알아야 할 때 쓰는 연산자가 sizeof예요. 예를 들어 배열 요소 수를 세거나 메모리를 잡을 때, 어떤 대상이 실제로 메모리를 얼마나 차지하는지 컴파일 타임에 확정하고 싶을 때 주로 사용해요.

출처: cppreference

본문

문법

sizeof( type ) (1)
sizeof expression (2)

두 형태 모두 size_t 타입의 값을 돌려줘요.

설명(Explanation)

  1. type의 객체 표현(object representation)의 크기를 바이트 단위로 돌려줘요.
  2. expression 타입의 객체 표현 크기를 바이트 단위로 돌려줘요. 이때 expression에는 암묵적 변환이 적용되지 않아요.

주의할 점(Notes)

컴퓨터 아키텍처에 따라 바이트는 8비트 이상으로 구성될 수 있고, 정확한 비트 수는 CHAR_BIT에 기록돼요.

sizeof(char), sizeof(signed char), sizeof(unsigned char)는 항상 1을 돌려줘요.

sizeof는 함수 타입, 불완전 타입(불완전 타입에는 void도 포함돼요), 또는 비트 필드 lvalue에는 쓸 수 없어요.

구조체 또는 공용체 타입의 피연산자에 적용하면 결과는 내부 패딩과 꼬리 패딩(trailing padding)을 모두 포함한 그 객체의 전체 바이트 수예요. 꼬리 패딩은 그 객체가 배열의 한 요소라면 그 배열의 다음 요소의 정렬 요구사항을 만족하도록 붙는 패딩이에요. 다시 말해 sizeof(T)T[] 배열의 한 요소 크기를 돌려준다고 볼 수 있어요.

type이 VLA 타입이고 그 크기 표현식의 값을 바꿔도 sizeof의 결과가 달라지지 않는 경우, 그 크기 표현식이 실제로 평가되는지는 구현이 정의(unspecified)해요. (C99부터)

expression의 타입이 VLA가 아니라면(C99부터) expression은 평가되지 않고, sizeof 연산자는 정수 상수 표현식으로 쓸 수 있어요.

expression의 타입이 가변 길이 배열 타입이면 expression은 평가되고, 그 배열이 평가되어 나온 크기가 런타임에 계산돼요. (C99부터)

배열 a(VLA 포함, C99부터)의 요소 수는 sizeof a / sizeof a[0] 표현식으로 구할 수 있어요. 다만 a가 포인터 타입이라면(예: 함수 매개변수 타입 조정으로 배열이 포인터로 바뀐 경우) 이 표현식은 그냥 포인터 타입의 바이트 수를 가리키는 타입의 바이트 수로 나눈 값이 되니 주의해야 해요.

키워드(Keywords)

sizeof

예제(Example)

아래 출력은 64비트 포인터와 32비트 int를 쓰는 플랫폼을 기준으로 한 예시예요.

#include <stdio.h>

int main(void)
{
    short x;
    // type argument:
    printf("sizeof(float)          = %zu\n", sizeof(float));
    printf("sizeof(void(*)(void))  = %zu\n", sizeof(void(*)(void)));
    printf("sizeof(char[10])       = %zu\n", sizeof(char[10]));
//  printf("sizeof(void(void))     = %zu\n", sizeof(void(void))); // Error: function type
//  printf("sizeof(char[])         = %zu\n", sizeof(char[])); // Error: incomplete type

    // expression argument:
    printf("sizeof 'a'             = %zu\n", sizeof 'a'); // type of 'a' is int
//  printf("sizeof main            = %zu\n", sizeof main); // Error: Function type
    printf("sizeof &main           = %zu\n", sizeof &main);
    printf("sizeof \"hello\"         = %zu\n", sizeof "hello"); // type is char[6]
    printf("sizeof x               = %zu\n", sizeof x); // type of x is short
    printf("sizeof (x+1)           = %zu\n", sizeof(x + 1)); // type of x+1 is int
}

가능한 출력:

sizeof(float)          = 4
sizeof(void(*)(void))  = 8
sizeof(char[10])       = 10
sizeof 'a'             = 4
sizeof &main           = 8
sizeof "hello"         = 6
sizeof x               = 2
sizeof (x+1)           = 4

몇 가지를 짚어 볼게요. sizeof 'a'4인 이유는 문자 리터럴 'a'의 타입이 C에서 int이기 때문이에요. sizeof &main은 함수를 가리키는 포인터라서 포인터 크기인 8이 나오고, sizeof "hello"는 널 종료자를 포함한 char[6] 크기로 6이에요.

더 알아보기

  • _Alignof(C11): 타입의 정렬 요구사항을 묻는 연산자.
  • 배열, 구조체, 공용체: sizeof의 피연산자로 쓰이는 복합 객체 타입.
  • VLA(가변 길이 배열, C99): sizeof가 런타임에 배열 크기를 계산하는 경우.