핵심 정리

구조체 멤버 정렬

C 언어는 CPU에서 메모리에 접근하는 효율을 높이기 위해 구조체를 일정한 크기로 정렬을 합니다. 이때 멤버 중에서 큰 자료형 크기의 배수로 정렬하며 남는 공간을 채우는 것을 패딩이라 부릅니다.

// 1 + 4 = 5 바이트 크기의 구조체
struct PacketHeader {
    char flags;    // 1바이트
    int offset;    // 4바이트
};

printf("%d\n", sizeof(struct PacketHeader)); // 8: 가장 큰 자료형은 int. int의 크기 4바이트로 정렬
                                             // 남는 3바이트는 패딩

구조체의 정렬 크기를 조절하려면 컴파일러에서 제공하는 지시자를 사용해야 합니다.

Visual Studio, GCC 4.0 이상

#pragma pack(push, 정렬크기)
#pragma pack(pop)

GCC 4.0 미만

__attribute__((aligned(정렬크기),packed))

구조체의 내용을 0으로 설정하기

구조체의 내용을 모두 0으로 설정하려면 memset 함수를 사용합니다.

memset(구조체포인터, 0, sizeof(struct 구조체));

구조체의 내용을 복사하기

구조체의 내용을 복사하려면 memcpy 함수를 사용합니다.

memcpy(목적지포인터, 원본포인터, sizeof(struct 구조체));

구조체 배열

구조체 변수를 선언하려면 [ ] (대괄호)에 크기를 지정합니다. 구조체 배열의 멤버에 접근하려면 [ ]에 인덱스를 지정한 뒤 .으로 접근합니다.

// 구조체 배열 선언하기
struct 구조체이름 변수이름[크기];

// 구조체 배열을 선언하는 동시에 값을 초기화
struct 구조체이름 변수이름[크기] = { { .멤버이름1 = 1, .멤버이름2 = 2 }, 
                                   { .멤버이름1 = 3, .멤버이름2 = 4 } };
struct 구조체이름 변수이름[크기] = { { 1, 2 }, { 3, 4 } };

배열[인덱스].멤버;         // 구조체 배열에서 요소의 멤버 값을 가져옴
배열[인덱스].멤버 = ;    // 구조체 배열에서 요소의 멤버에 값을 저장

구조체 포인터 배열

구조체 포인터 배열을 선언하려면 포인터 변수 이름 뒤에 [ ]를 붙인 뒤 크기를 지정합니다. 이때 배열의 요소에는 메모리를 할당해야 하며 멤버에 접근할 때는 [ ]에 인덱스를 지정한 뒤 ->로 접근합니다.

// 구조체 포인터 배열 선언하기
struct 구조체이름 *포인터이름[크기];

// 구조체 포인터 배열에 메모리 할당하기
for (int i = 0; i < 크기; i++)                   // 배열 크기만큼 반복
{
    배열[i] = malloc(sizeof(struct 구조체));    // 각 요소에 구조체 크기만큼 메모리 할당
}

배열[인덱스]->멤버;          // 구조체 포인터 배열에서 요소의 멤버 값을 가져옴
배열[인덱스]->멤버 = ;     // 구조체 포인터 배열에서 요소의 멤버에 값을 저장

// 구조체 포인터 배열의 메모리 해제하기
for (int i = 0; i < 크기; i++)    // 배열 크기만큼 반복
{
    free(포인터[i]);              // 각 요소의 동적 메모리 해제
}