본문 바로가기
Category/정보처리기사

C 언어 구조체(Structure)란?

by Corinee 2024. 10. 9.
728x90
반응형

C 언어에서 구조체(Structure)는 여러 종류의 데이터를 하나의 단위로 묶어 처리할 수 있는 매우 중요한 개념입니다. 기본적인 사용 방법 외에도, 구조체에 대해 더 깊이 이해할 필요가 있는 몇 가지 중요한 내용이 있습니다. 아래에 구조체와 관련된 주요 개념들을 설명드리겠습니다.

1. 구조체의 정의

  • 구조체(struct)는 다양한 자료형을 가진 변수들을 하나의 묶음으로 관리할 수 있는 사용자 정의 데이터 타입입니다.
  • 여러 개의 데이터를 하나의 논리적 단위로 묶어 처리할 수 있어 복잡한 데이터 구조를 만들 수 있습니다.

기본적인 구조체 정의:

typedef struct {
    int age;
    float height;
    char name[50];
} Person;

2. 구조체 변수 선언 및 초기화

구조체 변수를 선언하고 초기화하는 방법도 알아야 합니다.

선언 및 초기화 방법:

Person p1 = {25, 175.5, "John"};
  • 위 코드는 p1이라는 구조체 변수를 선언하고, 초기값으로 age = 25, height = 175.5, name = "John"을 설정한 예입니다.

3. 구조체 포인터

  • 구조체의 메모리 효율성을 높이기 위해 구조체 포인터를 사용하면 좋습니다. 포인터를 이용하면 구조체의 복사 없이 주소를 통해 데이터를 처리할 수 있습니다.

구조체 포인터 사용 예시:

Person p1 = {25, 175.5, "John"};
Person *ptr = &p1;  // 구조체 포인터 선언 및 초기화
printf("Name: %s\n", ptr->name);  // 화살표 연산자로 구조체 멤버 접근

4. 구조체 배열

  • 구조체의 배열을 선언하면 여러 개의 구조체 변수를 연속된 메모리 공간에 저장할 수 있습니다. 예를 들어, 여러 명의 사람 정보를 저장할 때 유용합니다.

구조체 배열 선언 예시:

Person people[3] = {
    {25, 175.5, "John"},
    {30, 180.3, "Jane"},
    {22, 165.2, "Tom"}
};

5. 구조체 내에서 포인터 멤버 사용

  • 구조체 안에 포인터 멤버를 정의하여 동적으로 메모리를 할당할 수 있습니다. 이를 통해 가변 크기의 데이터를 처리할 수 있습니다.

포인터 멤버를 포함한 구조체:

typedef struct {
    char *name;
    int age;
} Student;

int main() {
    Student s1;
    s1.name = (char *)malloc(20 * sizeof(char));  // 동적 메모리 할당
    strcpy(s1.name, "Alice");
    s1.age = 20;

    printf("Name: %s, Age: %d\n", s1.name, s1.age);
    
    free(s1.name);  // 동적 메모리 해제
    return 0;
}
  • 주의: 동적 메모리를 할당한 후에는 반드시 free() 함수를 사용하여 메모리를 해제해야 합니다.

6. 중첩 구조체 (Nested Structures)

  • 구조체 안에 다른 구조체를 멤버로 가질 수 있습니다. 이를 중첩 구조체라고 하며, 복잡한 데이터 구조를 표현할 때 유용합니다.

중첩 구조체 예시:

typedef struct {
    int day;
    int month;
    int year;
} Date;

typedef struct {
    char name[50];
    Date birthdate;  // 다른 구조체를 멤버로 가짐
} Employee;

7. 구조체의 크기와 메모리 패딩

  • 구조체의 크기는 각 멤버 변수의 크기에 따라 달라지지만, 메모리 패딩에 의해 크기가 예상보다 커질 수 있습니다. 메모리 패딩은 CPU의 성능을 최적화하기 위해 구조체 멤버를 정렬하는 방식입니다.

예시:

typedef struct {
    char a;  // 1바이트
    int b;   // 4바이트
} Example;
  • 위 구조체의 크기는 5바이트로 보일 수 있지만, 메모리 정렬 때문에 실제로는 8바이트가 될 수 있습니다.

8. typedef와 구조체

  • typedef를 사용하면 구조체 타입에 대한 별칭을 만들어 코드의 가독성을 높일 수 있습니다.

예시:

typedef struct {
    char name[50];
    int age;
} Person;

Person p1;  // 이제 struct Person 대신 Person을 바로 사용할 수 있음

9. 구조체와 함수

  • 구조체를 함수의 인수로 전달할 수 있습니다. 이때 값에 의한 전달 또는 포인터에 의한 전달 방식을 선택할 수 있습니다.

값에 의한 전달:

void printPerson(Person p) {
    printf("Name: %s, Age: %d\n", p.name, p.age);
}
  • 구조체가 함수에 값에 의한 전달로 넘겨지면, 구조체가 복사되어 전달됩니다. 대형 구조체의 경우 메모리와 성능이 비효율적일 수 있습니다.

포인터에 의한 전달:

void printPersonPtr(Person *p) {
    printf("Name: %s, Age: %d\n", p->name, p->age);
}
  • 포인터로 전달하면 주소만 전달되므로 메모리 효율이 높아집니다.

10. 구조체와 동적 메모리

  • 구조체를 사용할 때, 동적 메모리를 할당하고 해제하는 것이 중요합니다. 특히 구조체 내부에 포인터 멤버가 있을 경우 동적 메모리 관리를 잘 해야 메모리 누수를 방지할 수 있습니다.

요약

  • 구조체는 다양한 데이터를 하나로 묶어 관리하는 중요한 데이터 구조입니다.
  • 구조체의 멤버에 접근할 때는 점(.) 연산자와 화살표(->) 연산자를 사용합니다.
  • 구조체 포인터, 중첩 구조체, 구조체 배열 등을 통해 복잡한 데이터 구조를 관리할 수 있습니다.
  • 메모리 패딩구조체 크기를 고려해야 하며, 구조체와 함수의 효율적인 연동도 중요합니다.
  • 동적 메모리 할당메모리 해제를 관리하는 것이 중요한 개념입니다.

이러한 개념들은 C 언어에서 데이터 구조를 설계하고 처리할 때 매우 중요한 요소입니다.