sizeof는 크기 계산 도구이지만 배열 decay와 함수 경계 때문에 쉽게 오해됩니다.
- 배열 길이를
sizeof로 계산하는 코드가 왜 함수 안에서는 깨지는지 확인하고 싶다 malloc(sizeof(int) * n)보다sizeof *ptr가 왜 낫다는지 다시 보고 싶다sizeof가 값을 실제로 평가하는지 헷갈린다
숏컷 코드
size_t count = sizeof arr / sizeof arr[0];
int *p = malloc(sizeof *p * n);이 두 줄이 sizeof의 실전 핵심입니다.
문법
int arr[10];
size_t count = sizeof arr / sizeof arr[0];이건 배열이 실제 배열로 남아 있는 스코프에서만 맞습니다. 함수 인자로 넘어가면 배열은 포인터처럼 취급되므로 길이 정보가 사라집니다.
그래서 sizeof 카드는 결국 배열 decay 카드와 연결됩니다.
sizeof는 보통 식을 실제로 실행하는 게 아니라, 그 식이 어떤 타입 크기를 가지는지를 묻는 연산으로 읽는 편이 맞습니다.
int x = 0;
size_t n = sizeof(x + 1.0);그래서 sizeof는 "실행 결과"보다 "타입 크기"를 묻는 연산으로 읽는 편이 맞습니다.
사용 예시
int *p = malloc(sizeof *p * 100);이 패턴이 좋은 이유:
- 타입 이름을 두 번 안 쓴다
- 나중에 포인터 타입이 바뀌어도 크기가 같이 바뀐다
즉 "타입명을 다시 적어서 맞추는 습관"보다 오류 가능성이 낮습니다.
int *p = malloc(sizeof(int *) * 100); /* 잘못된 패턴 */이 코드는 int 원소가 아니라 포인터 크기만큼 잡을 수 있어서 자주 틀립니다.
체크포인트
- 함수 안에서 배열 길이 계산
sizeof(ptr)를 배열 전체 크기로 착각malloc(sizeof(Type *))처럼 별을 잘못 붙임
void print_all(int arr[]) {
size_t n = sizeof(arr) / sizeof(arr[0]); /* 포인터 크기 기준 */
}주의할 점
sizeof가 배열에서 잘 동작한 경험 때문에 함수 안에서도 같은 방식으로 길이를 구하려 하면 거의 반드시 틀립니다. C에서 배열 길이는 타입 시스템이 끝까지 보존해 주지 않는 정보라는 점을 계속 의식해야 합니다.
참고 링크
1 sources