`sizeof` 연산자(sizeof operator)
sizeof 연산자(sizeof operator)
객체나 타입의 실제 크기를 바이트 단위로 알아야 할 때 쓰는 연산자가 sizeof예요. 예를 들어 배열 요소 수를 세거나 메모리를 잡을 때, 어떤 대상이 실제로 메모리를 얼마나 차지하는지 컴파일 타임에 확정하고 싶을 때 주로 사용해요.
출처: cppreference
본문
문법
sizeof( type ) |
(1) |
sizeof expression |
(2) |
두 형태 모두 size_t 타입의 값을 돌려줘요.
설명(Explanation)
- type의 객체 표현(object representation)의 크기를 바이트 단위로 돌려줘요.
- 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가 런타임에 배열 크기를 계산하는 경우.