메모리 정렬(alignment) 및 **패딩(padding)**과 관련이 있습니다. C 언어에서 구조체는 멤버들을 특정 규칙에 맞춰 메모리 상에 배치합니다.

1. 메모리 정렬 (Alignment)

C 언어에서는 메모리 정렬(alignment)이라는 개념이 존재합니다. 각 데이터 타입은 특정 바이트 경계에 맞춰 메모리에서 정렬됩니다. 이 정렬은 CPU의 성능과 관련이 있으며, 데이터 접근을 최적화하려는 목적이 있습니다.

  • int 타입은 보통 4바이트 경계에 정렬되어야 합니다.
  • char 타입은 1바이트 크기이므로 1바이트 경계에 정렬됩니다.

따라서, C 언어에서 struct 내부에 여러 타입의 변수가 있을 때, 각 타입이 그에 맞는 정렬을 따르게 되며, 필요할 경우 패딩을 추가하여 정렬 규칙을 맞춥니다.

2. 패딩 (Padding)

패딩은 정렬 규칙을 맞추기 위해 자동으로 추가되는 메모리 공간입니다. C 언어에서는 메모리 정렬을 맞추기 위해, 데이터 타입의 크기가 해당 타입의 정렬 기준에 맞지 않으면 추가적인 바이트가 삽입됩니다.

예시:

struct NM { int age; // 4 bytes char name; // 1 byte };
  • int는 보통 4바이트 정렬을 요구합니다. age는 4바이트 경계에 맞게 정렬됩니다.
  • char는 1바이트 크기이고, 정렬에 특별한 제한이 없습니다. 하지만 name이 끝나고 난 후, 구조체의 크기가 4바이트 배수로 정렬되어야 할 수 있습니다. 즉, 구조체의 전체 크기가 4바이트 배수가 되도록 패딩이 추가됩니다.

구체적으로 설명하면:

  • age는 4바이트를 차지하고, 그 뒤에 1바이트 크기의 name이 옵니다. 그러면 name 뒤에 3바이트가 패딩으로 추가되어야 전체 크기가 4의 배수가 되도록 맞춰집니다.

따라서, 구조체 NM는:

  • age (4 bytes)
  • name (1 byte)
  • 패딩 (3 bytes)

이렇게 총 4 + 1 + 3 = 8바이트가 됩니다. 즉, sizeof(struct aaa)는 8이 됩니다.

요약:

sizeof(struct NM)가 4가 아니라 8인 이유는 int 타입의 정렬 요구사항과 구조체의 메모리 정렬 규칙에 의해 패딩이 추가되기 때문입니다.

3. 다른 언어에서의 메모리 정렬 및 패딩

C++:

C++도 C 언어와 비슷한 방식으로 구조체 내에서 메모리 정렬을 처리합니다. 따라서 C++에서도 같은 규칙을 따라 메모리 정렬을 맞추고, 패딩을 추가하여 구조체의 크기를 결정합니다.

Java:

Java는 기본적으로 32비트64비트 아키텍처에서 다른 메모리 정렬 방식을 사용합니다. Java에서는 내부적으로 객체를 정렬하는 방식이 다르고, int는 기본적으로 4바이트로 정렬됩니다. 그러나 Java는 메모리 정렬을 크게 신경 쓰지 않으며, 내부적으로 JVM이 최적화합니다. Java의 구조체는 사실 클래스 형태로 구현되며, 이 클래스는 JVM의 메모리 관리 방식을 따릅니다. Java에서는 일반적으로 sizeof를 사용하지 않지만, Object 크기는 JVM이 관리합니다.

Python:

Python은 C와 같은 시스템 수준 언어가 아니므로 구조체의 크기를 sizeof와 같이 직접적으로 계산할 필요가 없습니다. 그러나 struct 모듈을 사용하면 바이트 단위로 데이터를 처리할 수 있으며, 이 때는 C와 유사한 방식으로 정렬과 패딩을 처리합니다. Python에서 struct 모듈을 사용하여 C 스타일의 구조체를 만들 때도 메모리 정렬이 자동으로 적용됩니다.

Go:

Go 언어는 C와 유사한 메모리 정렬 규칙을 따르지만, 구조체의 각 필드는 8바이트 정렬을 기본으로 하며, Go는 이를 자동으로 관리합니다. Go에서 unsafe.Sizeof()를 사용하여 구조체 크기를 확인할 수 있습니다.

Rust:

Rust도 C와 유사하게 메모리 정렬을 자동으로 처리합니다. #[repr(C)] 어트리뷰트를 사용하여 C와 같은 방식으로 메모리 레이아웃을 강제할 수 있으며, 기본적으로 1, 2, 4, 8 등의 크기 단위로 정렬합니다. Rust에서는 std::mem::size_of::<T>()를 사용하여 구조체 크기를 확인할 수 있습니다.

4. 정리

C에서 sizeof(struct NM)가 4가 아니라 8인 이유는 메모리 정렬패딩 때문입니다. int는 4바이트 경계에서 정렬되어야 하고, 그 뒤에 위치한 char는 1바이트만 차지하지만, 구조체 전체 크기를 4의 배수로 맞추기 위해 추가적인 3바이트가 패딩으로 삽입됩니다.

다른 언어들에서도 비슷한 방식으로 메모리 정렬과 패딩이 적용되며, 그 방식은 언어의 구현과 메모리 관리 방식에 따라 다를 수 있습니다.

+ Recent posts