C언어 구조체와 공용체

김지원·2023년 3월 5일

C언어(독학사)

목록 보기
6/7

구조체

구조체의 개념과 선언

1) 구조체의 개념
: c언어에서 제공하고 있는 기본 자료형이 아닌 사용자의 필요에 의해 직접 만들어 사용할 수 있는 사용자 정의 자료형이다.

  • 서로 다른 종류의 변수들을 하나의 그룹으로 묶을 수 있는 구조 (다른 자료형일 경우에 배열을 사용할 수 없기에,,)

2) 구조체의 정의

struct 구조체 이름 {          → 구조체 정의를 위한 키워드
	자료형 멤버 변수1;
    자료형 멤버 변수2;
    ....
};

3) 구조체 선언 (3가지)
(1) 구조체 정의 후 필요할 떄 struct 키워드 이용해 구조체 변수 선언

struct STUDENT {
	int number;
    char name[10];
};
struct STUDENT st1, st2;

(2)(3) 정의와 동시에 구조체 변수를 선언.

struct STUDENT st1, st2 {
	int number;
    char name[10];
};
struct STUDENT {
	int number;
    char name[10];
} st1, st2;

(4) 구조체 정의 후 구조체 변수의 사용이 빈번하지 않은 경우

struct {
	int number;
    char name[10];
} st1, st2;          
  • 구조체 정의 시 구조체 이름을 정의하지 않고 바로 변수의 이름만 표기해 선언하는 방법이다. 이 경우 함수에서 매개변수나 반환값으로 구조체를 전달할 떄 변수의 자료형처럼 구조체 변수의 구조체명을 표기할 수 없으므로 인수나 반환값으로 사용할 수 없다.
    (5) typedef 를 이용해 구조체명을 다른 이름으로 다시 재정의하는 경우
typedef struct STUDENT {
	int number;
    char name[10];
} STD;
struct STD st1, st2;       

4) 구조체 초기화

struct STUDENT {
	int number;
    char name[10];
} st1 = {1, "김코딩"}, st2 = {2, "박코딩"};    // 초기화 부분

구조체 멤버의 참조

  • 정의된 구조체를 이용해 여러 구조체 변수를 선언하면 같은 이름의 멤버 변수가 이리 저리 쓰이게 되어 여러 개가 생기게 된다.
    이때 정확한 접근을 위해 어떤 구조체에 속한 멤버 변수인지 명시해주기 위해 구조체 변수명과 멤버이름 사이에 도트(.) 을 사용한다.
st1.num = 1
st2.num = 2

구조체 배열

: 같은 구조를 가진 구조체 변수가 여러 개 필요할 떄 그 변수들은 같은 자로형(구조체 유형)을 가지므로 배열을 선언할 수 있다.

struct STUDENT {
	int number;
    char name[10];
};
struct STUDENT st[2];
struct STUDENT st[2] = { {1, "김코딩"},{2, "박코딩"} }; → 구조체 배열의 초기화
st[0].num = 1                                       → 구조체 배열 멤버 참조
st[1].num = 2

구조체 포인터

: 구조체 변수의 주소를 저장한다.

  • 구조체 변수의 주소를 저장하기 위한 구조체 포인터도 해당 구조체의 이름으로 선언되어야한다.
struct STUDENT {
	int number;
    char name[10];
};
struct STUDENT st1, st2;
struct STUDENT *p1 = &st1;
struct STUDENT *p2 = &st2;
  • 구조체 포인터를 이용해 멤버를 참조하고자 할 떄는 dot(.) 혹은 포인터 (->) 를 이용한다.
p1.name
p1 -> name

함수의 구조체 변수

: 함수를 호출할 때 전달하는 매개 변수와 함수 종료 후 전달받는 반환값에 구조체를 이용하는 것이 가능하다.

1) 함수의 매개 변수로써 구조체 변수 사용하기

  • 변수의 자료형을 표기하는 것과 같이 구조체를 매개 변수로 사용할 경우 정의된 구조체의 이름을 표기해야한다
#include<stdio.h>
struct STD {
    int x,y;
    double area;
};
double Com(struct STD tri);         → 구조체 STD를 매개변수로 가지는 Com 함수 선언
void main() {
    struct STD triangle;            → 구조체 STD 변수 triangle 선언
    double area;
    triangle.x = 15;
    triangle.y = 7;
    area = Com(triangle);
    printf("area : %.2f\n", area);
}
double Com(struct  STD tri) {
    tri.area = tri.x * tri.y * 0.5;
    return tri.area;
}
<output>
area : 52.50

2) 함수의 매배 변수로써 구조체 포인터 사용하기

  • 함수의 호출 시 구조체의 주소를 전달하면 구조체의 값을 복사히진 않는다. 구조체의 주소를 전달할 떄는 주소를 저장하기 위한 4byte의 공간만 필요하기 때문에 기억공간의 낭비가 줄고 실행속도가 늘게 된다.
#include<stdio.h>
struct STD {
    int x,y;
    double area;
};
void Com(struct STD *tri);
void main() {
    struct STD triangle;
    triangle.x = 15;
    triangle.y = 7;
    Com(&triangle);                   → 구조체 변수 triangle의 주소를 넘겨준다. Com을 호출하고 함수 실행 후 반환된 값이 없으므로 횐쪽에 별도의 변수를 사용하지 않아도 된다.
    printf("area : %.2f\n", triangle.area);
}
void Com(struct  STD *tri) {          
    tri->area = tri->x * tri->y * 0.5;    → 포인터 연산자를 이용해 main() 함수에서 선언된 triangle 변수에 직접 접근한다.
}

구조체의 비트 필드

: byte 단위로 저장할 때 발생하는 저장공간의 낭비를 막기 위해 구조체 정의 시 각 멤버 변수들의 공간을 비트단위로 지정하는 구조.

  • 변수명 다음에 콜론(:)으로 필요한 비트 수를 지정한다.
struct time {
	unsigned int s : 6;
    unsigned int m : 6;
    unsigned int h : 5;
}

공용체

공용체란

: 정의된 멤버 변수들이 기억공간을 함께 공유하는 구조.
←→ 구조체는 정의된 멤버 변수들이 독립된 공간을 할당받음.

  • 멤버 변수들 중 가장 큰 기억공간을 필요로 하는 멤버 변수를 기준으로 할당된다.
union STUDENT {
	int number;
    char class;
    double avg;    ← 얘를 기준으로 기억공간 8byte 할당
}

공용체 사용

  • union 키워드를 사용하며 멤버 변수들이 기억공간을 공유하므로 멤버 변수의 값을 정할 때마다 기본 멤버 변수가 갖고 있던 값에 영향을 미치게 된다.
#include<stdio.h>
union STUDENT {
    int number;
    char class;
    double avg;
};
void main() {
    union STUDENT st;
    st.number = 2;
    printf("number :  %d\nclass : %c\navg : %f\n", st.number, st.class, st.avg);
    printf("----------------------\n");
    st.class = 'A';
    printf("number :  %d\nclass : %c\navg : %f\n", st.number, st.class, st.avg);
    printf("----------------------\n");
    st.avg = 123.45;
    printf("number :  %d\nclass : %c\navg : %f\n", st.number, st.class, st.avg);
    printf("----------------------\n");
    printf("st의 크기 : %d\n", sizeof(st));
}
<output>
number :  2
class : 
avg : 0.000000
----------------------
number :  65    
class : A                ← class 저장 후 출력하니 number 이 비정상적인 값이 되버어버림
avg : 0.000000
----------------------
number :  -858993459
class : \315		   
avg : 123.450000
----------------------
st의 크기 : 8				 ← st의 크기는 가장 많은 공간을 차지하는 avg에 double에 따라 8byte 기억공간이 할당되었다.

0개의 댓글