프로그래밍시스템 프로그래머

중첩 구조체와 C의 정렬(구조체 정렬) 작동 메커니즘을 설명하세요. 구조체의 크기를 어떻게 제어하고 어떤 문제가 발생할 수 있나요?

Hintsage AI 어시스턴트로 면접 통과

답변.

C 언어에서 구조체(struct)는 다른 구조체와 다양한 데이터 타입을 포함할 수 있습니다. 그러나 구조체 내 필드의 배치가 구조체의 크기와 정렬에 영향을 미칠 수 있습니다. 컴파일러는 가장 큰 필드에 대해 정렬(alignment)을 준수하기 위해 추가 바이트(padding)를 추가합니다. 이는 성능과 프로세서의 올바른 작동을 위해 중요합니다.

구조체가 중첩된 구조체를 포함하는 경우 정렬은 재귀적으로 적용됩니다:

  • 구조체의 크기는 항상 가장 큰 필드의 정렬에 배수입니다.
  • 중첩된 구조체는 예상치 못한 패딩을 발생시켜 sizeof(struct)가 필드의 sizeof 합계보다 클 수 있습니다.

크기를 제어하는 방법?

  1. 필드를 크기 내림차순으로 정렬합니다.
  2. 정렬 지시어를 사용합니다(예: MSVC의 #pragma pack 또는 GCC/Clang의 __attribute__((packed))).

예제:

#include <stdio.h> struct Inner { char c; int x; }; struct Outer { char a; struct Inner b; short s; }; int main() { printf("sizeof(struct Inner) = %zu\n", sizeof(struct Inner)); printf("sizeof(struct Outer) = %zu\n", sizeof(struct Outer)); return 0; } // sizeof(struct Inner) = 8 (64비트에서), sizeof(struct Outer) = 16 또는 24

pack과 packed를 사용하면 정렬을 무시하여 크기를 줄일 수 있지만, 이는 일부 플랫폼(ARM, DSP 등)에서 성능을 떨어뜨리거나 오류를 일으킬 수 있습니다.


함정 질문.

질문: 동일한 구조체의 크기가 모든 플랫폼에서 동일하다고 보장할 수 있나요?

답변: 아니요! C 표준은 동일한 정렬, 바이트 순서(endian)를 보장하지 않으며, 필드 간 및 구조체 끝에 padding을 "추가"할 수 있습니다. 구조체의 이진 호환성을 위해서는 정렬을 수동으로 관리하고 각 대상 플랫폼에서 항상 sizeof를 명시적으로 테스트해야 합니다.

예제:

struct Data { char c; int x; }; // sizeof(Data)는 일반적으로 64비트에서 8, 32비트에서 5 또는 8

역사

마이크로컨트롤러(ARM)와 PC 간에 이진 프로토콜을 통해 구조체를 교환할 때 ARM에서 전송된 데이터가 PC에서 예상과 일치하지 않았습니다 — 패딩과 바이트 순서가 달라서입니다. 이로 인해 잘못된 매개변수가 디코드되어 장치 제어의 물리적 오류를 초래했습니다.


역사

네트워크 프로토콜에서 데이터 전송 속도를 높이기 위해 packed-구조체를 추가했지만 정렬 없는 플랫폼에서 개별 필드가 작동하지 않는다는 것을 간과했습니다(프로세서가 미스 정렬 액세스를 지원하지 않았음). 최종 결과: 네트워크 패킷 작업 중 하드웨어 예외 발생.


역사

서버가 구조체 레코드로 구성된 외부 파일을 처리하고 있었습니다. 컴파일러 업데이트 후 구조체의 크기가 변경되었습니다(다른 정렬). 파일의 이전 데이터가 올바르게 읽히지 않게 되었고 일부 정보는 "손상된" 상태가 되었습니다.