C++ sizeof 연산자
1. 개요
1.1 문서 개요
이 문서는 C++에서 제공하는 sizeof
연산자에 관해 설명합니다. sizeof
는 컴파일 타임에 객체나 타입의 메모리 크기를 바이트 단위로 반환하는 연산자입니다. 해당 연산자는 메모리 최적화, 자료구조 설계, 버퍼 크기 계산 등 다양한 목적으로 사용되며, C++ 프로그래밍에서 데이터 크기에 민감한 시스템이나 네이티브 레벨 프로그래밍에서 자주 활용됩니다.
2. 내용
2.1 sizeof 연산자의 기본 개념과 특징
sizeof
는 타입 혹은 변수의 메모리 크기를 바이트 단위로 계산합니다. 컴파일 타임에 평가되므로 런타임 비용이 없으며, 리터럴 상수로 취급됩니다.
2.1.1 기본 문법
sizeof(type)
sizeof expression
두 가지 형식 모두 사용 가능하며, 타입에 대해서는 괄호가 필수이고, 변수에 대해서는 선택입니다.
int a = 10;
std::cout << sizeof(int); // 4 (일반적인 32비트 시스템 기준)
std::cout << sizeof a; // 4
2.1.2 반환 타입
sizeof
연산의 반환 타입은 size_t
입니다. 이는 <cstddef>
헤더에서 정의된 부호 없는 정수 타입입니다.
#include <cstddef>
size_t size = sizeof(double);
2.2 다양한 자료형에 대한 sizeof 결과
sizeof
는 기본 자료형, 사용자 정의 자료형, 배열, 포인터 등 다양한 타입에 적용 가능합니다.
2.2.1 기본 자료형
std::cout << sizeof(char); // 1
std::cout << sizeof(int); // 4
std::cout << sizeof(float); // 4
std::cout << sizeof(double); // 8
2.2.2 배열
배열의 크기를 구할 때 sizeof
는 전체 배열의 바이트 수를 반환합니다. 이를 이용해 배열의 요소 개수를 계산할 수 있습니다.
int arr[10];
std::cout << sizeof(arr); // 40 (10 * 4)
std::cout << sizeof(arr) / sizeof(int); // 10
2.2.3 포인터
포인터 변수에 대해 sizeof
를 적용하면, 해당 포인터의 크기(주소를 저장하는 데 필요한 크기)를 반환합니다. 일반적으로 64비트 시스템에서는 8바이트입니다.
int* ptr;
std::cout << sizeof(ptr); // 8 (64비트 시스템 기준)
2.3 구조체와 클래스에서의 sizeof
2.3.1 구조체와 클래스의 메모리 구조
sizeof
는 구조체나 클래스에 적용될 경우 멤버들의 크기를 합산한 후 정렬(padding)을 고려한 전체 크기를 반환합니다.
2.3.1.1 패딩 예시
struct A {
char a;
int b;
};
std::cout << sizeof(A); // 8 (패딩 포함)
이 경우 char
(1바이트) 다음에 3바이트의 패딩이 삽입되고, 그 다음 int
(4바이트)가 위치하여 총 8바이트가 됩니다.
2.3.2 패킹을 통한 구조체 크기 조절
컴파일러 지시자(pragma pack
)를 통해 구조체의 패딩을 조절할 수 있습니다.
#pragma pack(1)
struct B {
char a;
int b;
};
#pragma pack()
std::cout << sizeof(B); // 5 (패딩 없음)
2.4 sizeof와 동적 할당 객체
동적으로 할당된 객체의 크기는 sizeof
로 직접 알 수 없습니다. 해당 연산자는 포인터 자체의 크기만 반환하며, 포인터가 가리키는 실제 메모리 블록의 크기는 추적되지 않습니다.
int* p = new int[10];
std::cout << sizeof(p); // 8 (포인터 크기)
배열의 전체 크기를 알기 위해서는 별도의 추적 관리가 필요합니다.
2.5 sizeof와 함수
2.5.1 함수에는 적용 불가
sizeof
는 함수 자체에는 적용할 수 없습니다.
void func();
std::cout << sizeof(func); // 오류 발생
2.5.2 함수 포인터는 적용 가능
void func() {}
std::cout << sizeof(&func); // 함수 포인터 크기 반환
2.6 sizeof와 참조
참조 타입은 내부적으로 실제 객체를 대체하지 않으므로, 참조에 sizeof
를 적용하면 해당 참조가 가리키는 대상의 크기를 반환합니다.
int x = 100;
int& ref = x;
std::cout << sizeof(ref); // 4 (int의 크기)
2.7 sizeof와 사용자 정의 연산자 오버로딩
sizeof
는 컴파일 타임 연산자이기 때문에 오버로딩할 수 없습니다. 또한, 임의의 사용자 정의 타입에 대해 sizeof
를 사용해도 해당 타입 내부의 멤버 크기와 정렬에 따라 자동 계산됩니다.
3. 마무리
sizeof
연산자는 타입이나 객체의 메모리 크기를 컴파일 타임에 확인할 수 있는 정적 도구로, 메모리 레이아웃 이해와 최적화에 핵심적인 역할을 수행합니다. 배열, 구조체, 포인터 등 다양한 데이터 유형에 대해 동작하며, 정렬과 패딩이 결과에 영향을 줄 수 있습니다. 다만, 런타임 동적 할당 영역의 실제 크기는 sizeof
로는 확인할 수 없으므로, 동적 객체 관리에는 별도의 메커니즘이 요구됩니다.