배열이 타입이 같은 데이터들의 묶음이었다면 구조체는 타입이 다른 데이터들을 묶을 수 있는 방법이다.
구조체 정의와 선언
struct person {
char name[10];
int age;
float salary;
}; //구조체 정의
struct person a; //구조체 선언(메모리 공간 확보)
위의 구조체는 person이라는 이름을 가지며 char타입의 배열인 name. int타입의 age, float타입의 salary를 항목(fields)로 갖게 되는 것이다.
C언어에서는 구조체 변수를 선언할 때 struct와 구조체 이름을 같이 붙여야 한다.
typedef
typedef는 기존의 데이터 타입에 새로운 이름을 할당할 때 사용된다. 형식은 기존의 데이터 타입 다음 바꾸고자 하는 이름을 선언하면 된다. typedef를 구조체와 함께 쓰면 다음과 같은 형식이 된다.
typedef struct person { //구조체 정의
char name[10];
int age;
float salary;
} Person; //새로운 타입명 선언
Person a; //새로운 타입명으로 구조체 변수 선언
C언어의 구조체 선언에서는 struct와 구조체 이름을 같이 붙여 선언했어야 하는데 typedef를 이용하면 구조체 선언을 좀 더 간결하게 만들 수 있다.
구조체 멤버 연산자(member operator)
구조체 안의 특정 필드를 선택하고 싶을 때는 멤버 연산자 (.)을 이용하면 된다.
Person p1; //구조체 변수 선언
p1.age = 10; //age 필드에 10 대입
p1.salart = 35000; //salary 필드에 35000 대입
strcpy(p1.name, "james"); // name필드에 "james" 대입
구조체 안에 구조체(중첩 구조체)
구조체안에서 구조체를 필드로 갖는 것도 가능하다.
typedef struct{
int month;
int day;
int year;
} date;
typedef struct person {
char name[10];
int age;
float salary;
date dob; //구조체 안에서 구조체를 필드로 갖는 것이 가능
} Person;
이 경우 필드로 있는 구조체의 필드를 불러오고 싶다면 구조체로 필드를 멤버 연산자로 선택한 후 멤버 연산자를 한번 더 찍고 그 구조체의 필드를 불러오면 된다.
Person p1; //구조체 변수 선언
p1.dob.month = 2; // date 구조체의 변수 dob를 멤버연산자로 선택 후 다시 멤버 연산자로 해당 구조체의 day필드를 불러오기
p1.dob.day = 14;
p1.dob.year = 1988;
구조체간 대입과 비교 연산자
구조체와 구조체 사이의 대입과 비교 연산자를 이용한 연산은 가능할까.
초기 버전의 C언어에서는 허용되지 않았지만 최근의 C언어에서는 구조체 대입을 허용하고 있다. 구조체 단위로 모든 멤버들의 값을 복사하는 것이 가능하다.
typedef struct{
int hour;
int min;
int sec;
} time;
time first, second;
first = { 10, 56, 27 }; //first 변수에 구조체의 필드에 순서대로 값 저장(구조체 변수 초기화)
first = second; //구조체와 구조체 단위로 대입, 복사 가능
구조체간 비교 연산자를 이용하여 직접 비교를 하는 것은 불가능하다.
if(person1 == person2) //이렇게는 비교 불가
이 경우 어떤 경우에 같다라고 정의해야 하는지 혹은 다르다고 정의하는지 사용자 함수를 이용하여 프로그래머가 정해 줄 필요가 있다.
int humans_equal(person person1, person person2) {
if(strcmp(person1.name, person2.name))
return FALSE;
if(person1.age != person2.age)
return FALSE;
if(person1.salary != person2.salary)
return FALSE;
return TRUE; // 구조체의 각 멤버별로 구체적으로 정의
}