사이먼's 코딩노트

[C언어] 구조체(Struct) 본문

C언어

[C언어] 구조체(Struct)

simonpark817 2024. 2. 20. 17:31

[구조체]

  • 구조체(structure type)란 사용자가 C언어의 기본 타입을 가지고 새롭게 정의할  수 있는 사용자 정의 타입이다.
  • 구조체는 기본 타입(char, int, double, float 등)으로 나타낼 수 없는 복잡한 데이터를 표현할 수 있다.
  • 배열이 같은 타입의 변수 집합이라고 한다면, 구조체는 다양한 타입의 변수 집합을 하나의 타입으로 나타낸 것이다.
  • 간단하게 말해 구조체는 하나의 설계도를 의미한다고 생각하면 된다.
  • 아래는 구조체를 사용하기 전 통상적으로 우리가 사용하는 코드이다.
#include "stdio.h"

void introduce(int age, char* name, char* hometown, char* favorite_food, char* hobby);
void talk(int age, char* name, char* hometown, char* favorite_food, char* hobby);

int main() {
    int person1_age = 20;
    char* person1_name = "홍길동";
    char* person1_hometown = "한양";
    char* person1_favorite_food = "떡볶이";
    char* person1_hobby = "음악감상";

    int person2_age = 50;
    char* person2_name = "임꺽정";
    char* person2_hometown = "평양";
    char* person2_favorite_food = "떡국";
    char* person2_hobby = "영화감상";

    introduce(person1_age, person1_name, person1_hometown, person1_favorite_food, person1_hobby);
    talk(person1_age, person1_name, person1_hometown, person1_favorite_food, person1_hobby);

    introduce(person2_age, person2_name, person2_hometown, person2_favorite_food, person2_hobby);
    talk(person2_age, person2_name, person2_hometown, person2_favorite_food, person2_hobby);

    return 0;
}

void introduce(int age, char* name, char* hometown, char* favorite_food, char* hobby) {
    printf("== 소개 시작 ==\n");
    printf("이름 : %s\n", name);
    printf("나이 : %d살\n", age);
    printf("고향 : %s\n", hometown);
    printf("취미 : %s\n", hobby);
    printf("== 소개 끝 ==\n");
}

void talk(int age, char* name, char* hometown, char* favorite_food, char* hobby) {
    printf("이야기 시작 : 안녕하세요. 저는 %d살, %s 입니다. 제 고향인 %s 에서는...\n", age, name, hometown);
}
  • 위 코드는 person1과 person2의 나이, 이름, 고향, 좋아하는 음식, 취미를 변수로 생성하고 introduce와 talk 함수를 통해 자기소개를 하는 코드이다.
  • main 함수 위에 introduce()와 talk() 함수가 선언되었고 해당 함수의 로직은 main 함수 아래에 정의되어있다.
  • 만약 main 함수 아래에 사용자 지정의 함수를 정의하고 싶다면 위 코드 처럼 main 함수 위에서도 선언을 해줘야한다.
  • 그렇지 않고 main 함수 위에 사용자 지정의 함수를 정의하고 싶다면 위 코드처럼 따로 선언을 할 필요는 없다.
  • 우리는 위 코드를 Person 이라는 구조체를 만들어 새로운 타입을 만들어보려고 한다.
  • 아래는 같은 기능을 하는 코드지만, 구조체가 포함된 코드이다.

 

#include <stdio.h>

struct Person {
int age;
char* name;
char* hometown;
char* favorite_food;
char* hobby;
};

void introduce(struct Person p) {
    printf("== 소개 시작 ==\n");
    printf("이름 : %s\n", p.name);
    printf("나이 : %d살\n", p.age);
    printf("고향 : %s\n", p.hometown);
    printf("취미 : %s\n", p.hobby);
    printf("== 소개 끝 ==\n");
}


void talk(struct Person p) {
    printf("이야기 시작 : 안녕하세요. 저는 %d살, %s 입니다. 제 고향인 %s 에서는...\n", p.age, p.name, p.hometown);
}


int main(void) {
    struct Person p1;

    p1.age = 20;
    p1.name = "홍길동";
    p1.hometown = "한양";
    p1.favorite_food = "떡볶이";
    p1.hobby = "음악감상";

    struct Person p2;

    p2.age = 50;
    p2.name = "임꺽정";
    p2.hometown = "평양";
    p2.favorite_food = "떡국";
    p2.hobby = "영화감상";

    introduce(p1);
    talk(p1);
    introduce(p2);
    talk(p2);

    return 0;
}
  • 구조체의 기본 구조는 "struct 구조체이름 { };" 과 같다.
  • 대괄호{ } 밖에 반드시 세미콜론(;)을 붙혀줘야한다.
  • 위 코드는 struct Person 이라는 구조체를 정의하고 Person 이라는 구조체는 나이, 이름, 고향, 좋아하는 음식, 취미를 가진다는 것을 표현한다.
  • main 함수에서는 위에서 만든 Person의 구조체를 선언해야 한다. (struct Person p1)
  • Person 설계도를 가진 p1과 p2 변수를 생성해주고 p1과 p2의 각각 정보들을 입력한다.
  • p1.age, p1.name, p1.hometown, p1.favorite_food, p1.hobby 와 같이 . 을 통해 해당 구조체에서 선언한 멤버 변수를 불러온다.
  • 구조체를 사용하기 전에는 introduce()와 talk() 함수의 인자와 매개변수로 각 변수들을 입력했지만 구조체를 선언했을 때는 구조체 변수만 넘겨주면 된다.
  • 구조체의 기본 구조를 알았으니, 이번에는 구조체 변수의 주소를 이용해서 원본값을 변경하는 함수를 구현해보자.

 

#include <stdio.h>

struct School {
    char* name;
    int birth_date;
};

// 이 함수를 변경해야 합니다.
void change(struct School* s) {
    (*s).name = "미국초등학교";
    s->birth_date = 20180717;
}

int main(void) {
    struct School s1;

    s1.name = "한국초등학교";
    s1.birth_date = 19860404;

    printf("학교의 이름 : %s\n", s1.name);
    // 출력 => 학교의 이름 : 한국초등학교
    printf("학교의 설립일 : %d\n", s1.birth_date);
    // 출력 => 학교의 설립일 : 19860404

    change(&s1);

    printf("학교의 이름 : %s\n", s1.name);
    // 출력 => 학교의 이름 : 미국초등학교
    printf("학교의 설립일 : %d\n", s1.birth_date);
    // 출력 => 학교의 설립일 : 20180717

    return 0;
}
  • 위 코드는 구조체 변수 s1의 name과 birth_date를 change()라는 함수를 통해 값을 변경하는 코드이다.
  • 먼저, 코드 상단에 struct School 이라는 구조체를 선언하였고, School이라는 구조체는 멤버변수로 학교 이름과 개교기념일을 가지고있다.
  • change() 라는 함수는 인자로 그냥 s1을 넘기게 되면 값을 넘기게 되어 구조체 변수아닌 참조값이 change() 로 넘어가게된다.
  • 위와 같은 상황에서는 구조체 변수의 주소를 이용하여 원하는 값을 변경해야한다.
  • change(&s1) 과 같이 구조체 변수의 주소를 인자로 보내고 change() 함수에서는 s1의 주소값을 매개변수로 받아야한다.
  • void change(struct School* s) 와 같이 타입은 struct School 이고 포인터 변수 s를 적어준다.
  • 포인터 변수인 s의 값을 변경하기 위해서는 s의 주소로 이동해야되기 때문에 우리가 배웠던 *을 이용해서 이동할 수 있다.
  • *s.name이 아닌 (*s).name와 같이 ( )을 써준 이유는 연산자 순서에 따라서 s.name이 먼저 동작하기 때문에 s의 주소로 이동한 후 name을 찾아가야되기 때문이다.
  • *을 사용하지 않고 구조체 변수의 주소로 이동하는 방법이 있다.
  • s->birth_date 와 같이 '->' 을 사용하면 같은 기능을 한다.
반응형