본문 바로가기
프로그래밍/C언어

12. c언어 구조체

by 수삼이는코딩중 2023. 3. 22.
728x90

struct

구조체

sims게임을 만들 때, 캐릭터에 대한 정보가 너무 많이 들어간다
따라서 원소의 크기가 제각각인 배열을 만들 수 있으면 ?
한사람에 대한 정보를 한개의 배열에 저장 할 수 있으면?
즉, 첫번째 원소는 int로 나이를, 두번째원소는 char[]로 이름을! 하지만 c언어에서 배열은 원소의 타입이 모두 동일해야 한다.
다행히도 c언어에서는 배열로 해결하지 못하는 문제를 구조체를 이용하여 해결할 수 있다.

#include <stdio.h> 
struct Human {
  int age;
  int height;
  int weight;
};

int main(){
  struct Human Psi;
  
  Psi.age=99;
  Psi.height=185;
  Psi.weight=80;
  
  printf("Psi information\n");
  printf("age : %d\n",Psi.age);
  printf("height : %d\n",Psi.height);
  printf("weight : %d\n",Psi.weight);
  return 0;
  }

 

구조체는 각 원소의 타입이 제각각인 배열이기 때문에 모든 원소의 타입을 명시해 주어야 한다.
Human이라는 이름의 구조체는 3개의 멤버를 가지고 있다
각각의 멤버는

int age
int height
int weight


구조체 포맷

struct 구조체명 {
멤버타입 멤버명;
};


꼭 마지막 중괄호가 끝나면 ; 를 붙인다!!

메인함수에 선언할 때는

struct 구조체이름 구조체변수명;

으로 구조체변수를 선언해준다. (구조체변수의 타입은 struct 구조체이름, 즉 Human 구조체 가된다)

배열에서는 []를 이용하여 원소에 접근했는데, 구조체에서는 .를 이용하여 멤버에 접근한다.

구조체변수명.멤버명

단, 배열과의 차이는 구조체 내부에서는 변수를 초기화 할 수 없다(당연하겠지,, 클래스 느낌!..?)

#include <stdio.h> 
struct Books {
    char name[30];
    char auth[30];
    char publ[30];
    int borrowed;
};

int main(){   
    struct Books book_list[3];
    int i;   
    for (i=0;i<3;i++){
        printf("책 정보 입력 : \n");
        scanf("%s %s %s", book_list[i].name, book_list[i].auth, book_list[i].publ);
        book_list[i].borrowed =0;
      }   
    for (i=0;i<3;i++){
        printf("-----------------\n");
        printf("책 %s의 정보\n",book_list[i].name);
        printf("저자 : %s \n",book_list[i].auth);
        printf("출판사 : %s \n",book_list[i].publ);     if (book_list[i].borrowed ==0){
          printf("안 빌려짐\n");
        }
    else {
      printf("빌려짐\n");
    }
  }
  
  return 0;
}

구조체포인터

구조체는 배열, 문자열 처럼 구조체 변수명에 메모리 시작주소값이 들어가있지 않다. 그냥 구조체의 변수명 일 뿐이다!
그래서 변수를 가리키듯 사용하면 된다.

int a;
int *b;
b=&a


처럼 사용!!

#include <stdio.h> 
struct test{
    int a,b;
};
int main(){
  struct test st;
  struct test *ptr;   
  ptr = &st;   
  (*ptr).a = 1;
  (*ptr).b = 2;   
  printf("%d, %d",st.a,st.b);
  
  return 0;
}


구조체포인터를 이용해 구조체에있는 변수에 접근하려면
*b==a이기 때문에

(*b).멤버명

과 같이 접근하면 된다.

단, 반드시 괄호로 감싸줘야 하는데 그 이유는
연산 우선순위가 다음과 같기 때문이다

. //구조체의 변수에 접근하는 연산자
* //포인터 연산자

이때
*b.멤버명
와 같이 접근한다면 우선순위에 따라 *(b.멤버명)과 같이 연산이 이루어지는데
b는 구조체도 아닌, 포인터일 뿐이기 때문에 그 어디에도 접근하는 것이 아니기 때문이다.

이 귀찮은 작업을 쉽게 할 수있도록 한 c언어! 다음을 보자.

include <stdio.h>

struct test{
    int a,b;
};
int main(){
  struct test st;
  struct test *ptr;

  ptr = &st;

  ptr->a = 1;
  ptr->b = 2;

  printf("%d, %d",st.a,st.b);
  
  return 0;
}


(*ptr).a를 ptr->a 로 쓸 수 있다. (사용자 편의를 위해 도입한 기호!!)

 

구조체 내부에 있는 구조체의 멤버에 값을 입력할 때

int main(){
    struct simple c1 = {10, 10, 1.5}; // 순서대로 채워짐
    struct simple c2 = {{30,30},2.4}; // 순서대로 채워짐
    struct simple c3 = {1,1}; // 내부구조체에만 차례로 채워짐
    struct simple c4 ={{1},1};// 내부구조체의 첫번째 멤버에 1, 구조체의 멤버에 1이 채워짐
    return 0;
}

굳이 구조체 안에 구조체를 넣기보다는 포인터를 사용하면 메모리상 좋다.

  • 구조체를 포함하는 구조체는 자기 자신은 포함할 수 없다. -> 에러발생
  • 자기 자신을 가리키는 포인터는 사용할 수 있다. 

댓글