C언어 구조체 변수 선언과 사용법 완벽 가이드

C언어에서 구조체는 서로 관련이 있는 여러 데이터를 하나의 단위로 묶어서 처리할 수 있는 강력한 데이터 타입입니다. 구조체를 사용하면 복잡한 데이터를 효율적으로 관리하고, 프로그램의 가독성 및 유지보수성을 높일 수 있습니다. 본 기사에서는 C언어에서 구조체 변수를 선언하고 사용하는 방법을 자세히 설명합니다.

목차

구조체란 무엇인가


구조체는 C언어에서 다양한 데이터 타입을 하나의 단위로 묶을 수 있는 사용자 정의 데이터 타입입니다. 예를 들어, 학생 정보를 관리한다고 할 때 이름, 나이, 학번 등 여러 개의 데이터가 필요합니다. 이때 각 데이터를 하나의 구조체로 묶어 관리할 수 있습니다.

구조체의 사용 목적


구조체는 다음과 같은 목적으로 사용됩니다:

  • 복잡한 데이터 관리: 서로 관련 있는 다양한 데이터를 하나로 묶어서 처리할 수 있습니다.
  • 가독성 향상: 여러 개의 변수를 개별적으로 사용하는 것보다 구조체를 활용해 더 명확하고 직관적으로 코드를 작성할 수 있습니다.
  • 유지보수 용이성: 관련 데이터들이 구조체로 묶여 있으면 코드 수정이 용이하고, 유지보수가 쉬워집니다.

예시: 학생 정보 관리


학생의 이름, 나이, 학번을 구조체로 정의하고 이를 하나의 단위로 관리할 수 있습니다.

struct Student {
    char name[50];
    int age;
    int student_id;
};


이렇게 정의한 구조체 Studentname, age, student_id라는 세 가지 필드를 포함하게 됩니다.

구조체 변수 선언 기본


구조체를 사용하려면 먼저 구조체 타입을 정의하고, 그 후 해당 타입을 사용하여 변수를 선언해야 합니다. 구조체 정의는 struct 키워드를 사용하여 이루어집니다.

구조체 정의 예시


먼저, 구조체를 정의합니다. 예를 들어 학생 정보를 담는 구조체를 선언하려면 아래와 같이 작성할 수 있습니다.

struct Student {
    char name[50];  // 학생 이름
    int age;        // 학생 나이
    int student_id; // 학생 학번
};

이 구조체는 name, age, student_id라는 세 가지 필드를 포함하고 있으며, 각각 학생의 이름, 나이, 학번을 저장합니다.

구조체 변수 선언 예시


구조체를 정의한 후, 이를 기반으로 실제 변수들을 선언할 수 있습니다. 아래는 Student 구조체 타입을 사용해 변수 s1s2를 선언하는 예시입니다.

struct Student s1, s2;

위 코드에서 s1s2Student 구조체 타입의 변수로, 각기 다른 학생 정보를 저장할 수 있습니다. 구조체 변수는 여러 개를 선언하여 사용할 수 있습니다.

구조체 변수 선언과 초기화


구조체 변수를 선언한 후에는 해당 구조체 변수의 각 멤버에 값을 할당하여 초기화할 수 있습니다. 이 과정은 구조체 변수를 사용할 준비를 하는 중요한 단계입니다.

구조체 변수 초기화 예시


구조체 변수를 선언한 후, 각 멤버에 값을 할당하는 방법은 매우 직관적입니다. 아래 예시를 통해 구조체 변수를 초기화하는 방법을 살펴보겠습니다.

struct Student s1;
s1.age = 20;
strcpy(s1.name, "John");
s1.student_id = 12345;

위의 예시에서 s1이라는 구조체 변수의 각 멤버인 age, name, student_id에 값을 할당하고 있습니다. 특히 문자열인 name을 초기화할 때는 strcpy 함수로 문자열을 복사해야 합니다.

구조체 선언과 동시에 초기화


구조체를 선언하면서 동시에 값을 초기화할 수도 있습니다. 이 방법은 코드의 가독성을 높이고, 초기화 과정을 한 줄로 간단히 처리할 수 있게 해줍니다.

struct Student s2 = {"Alice", 22, 67890};

이 예시에서는 s2라는 구조체 변수를 선언하면서 이름은 "Alice", 나이는 22, 학번은 67890으로 초기화하고 있습니다. 구조체 선언과 초기화가 동시에 이루어지는 방식으로, 코드가 간결해집니다.

구조체 멤버 접근 및 사용


구조체 변수를 선언하고 초기화한 후, 해당 변수의 멤버에 접근하여 데이터를 처리할 수 있습니다. 구조체의 멤버에 접근하는 방법과 이를 활용하는 방식에 대해 알아보겠습니다.

구조체 멤버 접근


구조체 변수의 각 멤버는 점(.) 연산자를 사용하여 접근할 수 있습니다. 예를 들어, s1이라는 구조체 변수의 name이나 age 멤버를 출력하려면 다음과 같이 작성합니다.

printf("Student Name: %s\n", s1.name);
printf("Student Age: %d\n", s1.age);

위 코드에서 s1.names1 구조체 변수의 name 멤버에 접근하는 방식이며, s1.ageage 멤버에 접근하는 방식입니다. printf 함수를 사용하여 구조체 멤버 값을 출력할 수 있습니다.

구조체 멤버 수정


구조체 멤버에 값을 수정하는 것도 간단합니다. 예를 들어, s1의 나이를 21로 변경하려면 아래와 같이 작성합니다.

s1.age = 21;

이렇게 점(.) 연산자를 사용하여 구조체의 멤버에 직접 값을 할당하거나 수정할 수 있습니다.

구조체 변수를 통한 데이터 처리


구조체 변수는 여러 데이터가 하나의 단위로 묶여 있기 때문에, 복잡한 데이터를 처리할 때 유용합니다. 예를 들어, 학생 정보를 저장한 후 해당 정보를 출력하거나 수정하는 등의 작업을 효율적으로 할 수 있습니다.

void printStudent(struct Student s) {
    printf("Name: %s\n", s.name);
    printf("Age: %d\n", s.age);
    printf("Student ID: %d\n", s.student_id);
}

위 함수 printStudentStudent 구조체를 인자로 받아 해당 학생의 정보를 출력하는 함수입니다. 구조체를 함수의 인자로 전달함으로써 데이터 처리와 관련된 작업을 효율적으로 관리할 수 있습니다.

구조체 포인터 사용


구조체 포인터는 구조체 변수의 주소를 저장하는 포인터로, 구조체에 대한 효율적인 접근을 제공합니다. 구조체 포인터를 사용하면 직접 구조체 멤버를 수정하거나 조회할 수 있으며, 특히 함수에 구조체를 전달할 때 유용합니다.

구조체 포인터 선언


구조체 포인터를 선언하려면, 먼저 구조체 타입을 포인터로 선언해야 합니다. 아래는 Student 구조체의 포인터를 선언하는 예시입니다.

struct Student *ptr;

이 예시에서는 ptrStudent 구조체를 가리키는 포인터로 선언됩니다. 구조체 포인터는 구조체 변수의 주소를 저장합니다.

구조체 포인터에 주소 할당


구조체 포인터는 특정 구조체 변수의 주소를 저장해야 하므로, 구조체 변수의 주소를 할당해야 합니다.

struct Student s1;
struct Student *ptr = &s1;

위 코드에서 ptrs1 구조체 변수의 주소를 저장하는 구조체 포인터입니다.

구조체 포인터로 멤버 접근


구조체 포인터를 사용하여 구조체의 멤버에 접근할 때는 -> 연산자를 사용합니다. ->는 구조체 포인터가 가리키는 구조체의 멤버에 접근할 때 사용되는 연산자입니다.

ptr->age = 25;
strcpy(ptr->name, "Michael");
ptr->student_id = 54321;

위 코드에서는 ptr 포인터를 사용하여 s1 구조체의 age, name, student_id 멤버에 접근하고 값을 수정하고 있습니다. -> 연산자는 포인터가 가리키는 구조체의 멤버를 쉽게 수정할 수 있게 도와줍니다.

구조체 포인터와 함수


구조체 포인터를 함수 인자로 전달하여 구조체 멤버에 접근하거나 수정할 수 있습니다. 구조체 포인터를 사용하면 값 복사가 아니라 원본 구조체를 직접 수정할 수 있습니다.

void updateStudent(struct Student *s) {
    s->age = 26;  // 구조체 멤버 수정
    strcpy(s->name, "John Doe");
}

이 함수는 Student 구조체 포인터를 받아 해당 구조체의 데이터를 수정합니다. 함수 호출 시 구조체의 포인터를 전달하면, 구조체의 원본 데이터를 직접 수정할 수 있습니다.

구조체 배열 사용


여러 개의 구조체 변수를 관리할 때 구조체 배열을 사용할 수 있습니다. 구조체 배열은 동일한 타입의 구조체 변수를 여러 개 저장할 수 있는 데이터 구조로, 주로 동일한 종류의 데이터를 여러 개 처리할 때 유용합니다.

구조체 배열 선언


구조체 배열을 선언하려면 먼저 구조체 타입을 정의한 후, 배열을 선언합니다. 예를 들어, 5명의 학생 정보를 관리하는 구조체 배열을 선언하려면 다음과 같이 작성할 수 있습니다.

struct Student {
    char name[50];
    int age;
    int student_id;
};

struct Student students[5];

위 코드에서 students 배열은 5명의 학생 정보를 저장할 수 있는 구조체 배열입니다. 각 배열 요소는 Student 구조체 타입의 변수로, 각 학생의 데이터를 관리합니다.

구조체 배열 초기화


구조체 배열을 선언하면서 동시에 초기화할 수 있습니다. 배열의 각 인덱스마다 구조체를 초기화하려면 아래와 같이 할 수 있습니다.

struct Student students[2] = {
    {"John", 20, 12345},
    {"Alice", 22, 67890}
};

위 코드에서는 students 배열에 두 명의 학생을 초기화하여 값을 저장하고 있습니다. 각 인덱스에 대해 이름, 나이, 학번을 지정하고 있습니다.

구조체 배열 사용 예시


배열의 각 요소에 접근할 때는 인덱스를 사용하며, 점(.) 연산자로 구조체의 멤버에 접근할 수 있습니다. 예를 들어, 첫 번째 학생의 이름을 출력하려면 아래와 같이 작성합니다.

printf("Student 1 Name: %s\n", students[0].name);

구조체 배열을 사용하여 반복문을 통해 여러 개의 구조체 멤버에 접근하거나, 배열의 각 요소에 대한 처리를 쉽게 할 수 있습니다. 예를 들어, 배열에 저장된 모든 학생의 정보를 출력하려면 다음과 같은 코드를 사용할 수 있습니다.

for (int i = 0; i < 5; i++) {
    printf("Student Name: %s, Age: %d, ID: %d\n", students[i].name, students[i].age, students[i].student_id);
}

이 코드에서는 students 배열의 각 요소를 순차적으로 접근하여, 각 학생의 이름, 나이, 학번을 출력하고 있습니다.

구조체 배열의 활용


구조체 배열은 동일한 데이터 구조를 여러 개 다루는 데 유용합니다. 예를 들어, 수십 명 이상의 학생 정보를 저장하거나, 여러 개의 도서 정보를 관리할 때 구조체 배열을 활용할 수 있습니다.

구조체와 함수


구조체는 함수의 인자로 전달하거나 함수에서 반환값으로 사용할 수 있습니다. 이를 통해 구조체를 보다 효율적으로 처리할 수 있으며, 복잡한 데이터를 함수 내에서 처리할 때 유용합니다. 구조체를 함수와 함께 사용하는 방법에 대해 자세히 살펴보겠습니다.

구조체를 함수의 인자로 전달하기


구조체를 함수의 인자로 전달할 수 있습니다. 이 경우 구조체 변수는 함수 내에서 복사되어 사용됩니다. 구조체를 함수의 인자로 전달하려면 구조체 타입을 함수의 파라미터로 지정하고, 해당 구조체 변수나 포인터를 전달합니다.

void printStudent(struct Student s) {
    printf("Name: %s\n", s.name);
    printf("Age: %d\n", s.age);
    printf("Student ID: %d\n", s.student_id);
}

위 함수는 Student 구조체를 인자로 받아 해당 구조체의 멤버 값을 출력하는 함수입니다. 함수 호출 시 구조체 변수 s1을 전달하면, 그 복사본이 함수 내에서 사용됩니다.

struct Student s1 = {"Tom", 20, 10101};
printStudent(s1);

이렇게 하면 s1의 값이 printStudent 함수에 전달되어 출력됩니다.

구조체 포인터를 함수 인자로 전달하기


구조체를 복사해서 전달하는 대신, 구조체의 포인터를 전달하면 함수 내에서 원본 구조체 데이터를 수정할 수 있습니다. 구조체 포인터를 함수 인자로 전달하면 더 효율적으로 데이터를 처리할 수 있습니다.

void updateStudent(struct Student *s) {
    s->age = 22;  // 구조체 멤버 수정
    strcpy(s->name, "John Doe");
}

위 함수는 Student 구조체의 포인터를 인자로 받아 해당 구조체의 멤버 값을 수정하는 함수입니다. 구조체 포인터를 전달할 때는 -> 연산자를 사용하여 멤버에 접근합니다.

struct Student s1 = {"Tom", 20, 10101};
updateStudent(&s1);
printf("Updated Name: %s, Age: %d\n", s1.name, s1.age);

이 예시에서는 &s1을 사용해 s1의 주소를 updateStudent 함수에 전달하고 있습니다. 이렇게 하면 함수 내에서 s1의 데이터를 직접 수정할 수 있습니다.

구조체를 함수에서 반환하기


구조체를 함수에서 반환할 수도 있습니다. 이 경우 함수에서 반환된 구조체를 변수에 저장하여 사용할 수 있습니다.

struct Student createStudent(char name[], int age, int student_id) {
    struct Student s;
    strcpy(s.name, name);
    s.age = age;
    s.student_id = student_id;
    return s;
}

위 함수는 새로운 Student 구조체를 생성하여 반환합니다. 반환된 구조체는 createStudent 함수 외부에서 사용할 수 있습니다.

struct Student s1 = createStudent("Alice", 21, 10234);
printf("Name: %s, Age: %d, ID: %d\n", s1.name, s1.age, s1.student_id);

이와 같이 함수에서 반환된 구조체를 사용하여 데이터를 처리할 수 있습니다.

구조체와 함수 활용의 장점


구조체를 함수와 함께 사용하면 다음과 같은 장점이 있습니다:

  • 데이터 캡슐화: 관련 데이터를 하나의 구조체로 묶어 함수 내에서 처리할 수 있습니다.
  • 유연성: 구조체를 인자로 전달하거나 반환함으로써 복잡한 데이터 처리 작업을 함수 간에 유연하게 처리할 수 있습니다.
  • 메모리 효율성: 구조체 포인터를 사용하여 데이터를 복사하지 않고 원본 데이터를 수정할 수 있습니다.

구조체와 함수의 조합은 프로그램을 보다 효율적이고 관리하기 쉽게 만들어 줍니다.

구조체와 typedef


C언어에서 typedef는 구조체 타입에 별칭을 붙여서 코드의 가독성을 높이고, 구조체 타입을 보다 쉽게 사용할 수 있도록 도와줍니다. 구조체에 typedef를 사용하면 코드가 간결해지고, 구조체 선언을 반복하지 않게 되어 코드 유지보수가 용이해집니다.

typedef로 구조체 타입 별칭 만들기


typedef를 사용하면 구조체의 이름을 별칭으로 사용할 수 있게 됩니다. 이를 통해 구조체를 정의할 때마다 struct 키워드를 반복해서 작성할 필요가 없어집니다. 아래는 typedef를 사용하여 Student 구조체에 별칭을 붙인 예시입니다.

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

위 코드에서는 struct 키워드를 생략하고, typedef를 사용하여 Student라는 별칭을 붙였습니다. 이제 Student는 구조체 타입을 나타내며, 구조체를 선언할 때 더 이상 struct 키워드를 사용할 필요가 없습니다.

typedef를 사용한 구조체 변수 선언


typedef를 사용한 후에는 구조체 변수 선언을 간단히 할 수 있습니다. 예를 들어, Student 구조체를 선언하고 사용하는 방법은 다음과 같습니다.

Student s1;  // 구조체 변수 선언
s1.age = 21;
strcpy(s1.name, "David");
s1.student_id = 1001;

이렇게 typedef를 사용하면 코드가 간결해지고, 구조체 선언 시 struct 키워드를 반복할 필요가 없어집니다.

typedef와 구조체 포인터


typedef는 구조체 포인터에도 적용할 수 있습니다. 이를 통해 구조체 포인터를 선언할 때 코드의 가독성을 더욱 향상시킬 수 있습니다.

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

Student *ptr;  // 구조체 포인터 선언

위 예시에서는 Student *ptr을 사용하여 구조체 포인터를 선언하는데, typedef 덕분에 struct 키워드를 반복하지 않아도 됩니다.

typedef의 장점


typedef는 구조체를 사용할 때 다음과 같은 장점을 제공합니다:

  • 코드 간결화: typedef를 사용하면 매번 struct를 반복할 필요 없이 구조체 타입을 간단히 사용할 수 있습니다.
  • 가독성 향상: 별칭을 사용함으로써 구조체 타입을 직관적으로 나타낼 수 있어 코드의 가독성이 향상됩니다.
  • 유지보수 용이: 구조체 타입 이름을 변경해야 할 때, typedef를 사용하면 코드에서 별칭만 변경하면 되어 유지보수가 용이합니다.

따라서 typedef는 구조체를 효율적으로 관리하고, 코드의 가독성과 유지보수성을 높이는 데 매우 유용합니다.

요약


본 기사에서는 C언어에서 구조체 변수를 선언하고 사용하는 방법에 대해 다루었습니다. 구조체는 관련 데이터를 하나의 단위로 묶어 관리할 수 있는 유용한 도구로, 변수 선언, 초기화, 멤버 접근, 포인터 활용 등 다양한 방식으로 사용될 수 있습니다. 또한, 구조체 배열과 함수에서의 활용법, typedef를 사용한 구조체 타입의 별칭 지정 방법까지 설명하였습니다.

구조체를 잘 활용하면 복잡한 데이터를 보다 체계적이고 효율적으로 처리할 수 있습니다. 구조체를 선언하고, 변수를 초기화하며, 함수와 연계하여 데이터 처리 작업을 수행하는 과정은 프로그램의 품질과 유지보수성을 크게 향상시킵니다.

목차