13-1.구조체

13-1-가.정의

구조체는 C의 데이터 타입중에 가장 덩치가 크다. 정수나 실수 또는 문자열 등의 단순한 형태로 나타낼 수 없는 복잡한 데이터를 표현할 때 구조체를 사용한다. 표준 함수 중에 구조체를 사용하는 함수가 있고 윈도우즈에서도 구조체가 아주 흔하게 사용된다. 다행히 구조체는 덩치만 컸지 개념이 간단하기 때문에 별로 어렵지는 않다. 물론 구조체를 이해하는 것과 구조체를 제대로 잘 쓰는 것은 별개의 문제지만 말이다. 일단 구조체의 정의부터 내려 보자.

구조체(Structure)를 문장화하여 정의 내리면 "타입이 다른 변수들의 집합"이라고 할 수 있으며 더 간단하게 표현하면 이종 변수 집합이다. 배열이 타입이 같은 변수들의 집합인 것에 비해 구조체는 다른 타입을 가지는 변수들을 하나의 이름으로 묶어둔 것이다. 한 사람의 신상 정보를 표현하고자 한다면 다음과 같은 변수들이 필요할 것이다.

 

char Name[10];

int Age;

double Height;

 

Name은 사람의 이름을 가지는 문자열이며 Age는 나이 정보를 가지는 정수형 변수이고 Height는 이 사람의 키가 얼마나 되는지를 기억한다. 좀 더 자세한 정보들을 기억시키고자 한다면 이 외에도 주소나 전화 번호, 혈액형, 성별 따위의 많은 정보들이 필요할 것이다. 보다시피 각 변수들의 타입이 서로 다르기 때문에 배열로 이 변수들을 묶을 수는 없다. 이런 관련성있는 정보들을 하나로 묶어서 선언하고자 할 때 사용하는 타입이 바로 구조체이다. 여러 가지 정보들이 모여서 하나의 완성된 정보를 구성하는 예는 실생활에서도 아주 많이 찾을 수 있다.

 

도서 정보 : 저자, 출판사, 출판 년도, 총 페이지수, 가격, 도서 번호

상품 정보 : 상품명, 제조사, 용량, 입고일, 매입가, 판매가, 할인율

게임의 주인공 : 현재 위치, 현재 모양, 보유한 아이템, 에너지 상태

 

관련 정보를 하나의 구조체로 묶어서 선언하면 양이 많은 정보도 쉽게 다룰 수 있으며 함수를 통해 복잡한 정보를 전달하거나 리턴받을 수도 있다. 구조체를 선언할 때는 예약어 struct를 사용한다. 신상 정보를 기억하는 세 개의 변수를 Friend라는 이름의 구조체로 묶어서 표현하고 싶다면 다음과 같이 선언한다.

 

struct {

     char Name[10];

     int Age;

     double Height;

} Friend;

 

struct { } 블록안에 구조체에 포함되는 변수들의 목록을 순서대로 선언하고 구조체 변수의 이름을 끝에 적으면 된다. 구조체 변수를 선언하는 기본 형식은 "struct { 멤버목록 } 변수명;"이다. 구조체 선언문도 하나의 문장이므로 끝의 세미콜론을 빼먹지 않도록 주의하자.

Name, Age, Height처럼 구조체에 속한 변수들을 멤버(Member)라고 하는데 struct 블록안에 일반 변수를 선언할 때와 똑같은 방법으로 선언하면 된다. 구조체의 멤버가 될 수 있는 타입에는 전혀 제한이 없다. 정수형, 실수형 같은 기본형은 물론이고 포인터, 배열 심지어 구조체가 다른 구조체의 멤버로 포함될 수도 있다. 또한 멤버의 개수에도 제한이 없으므로 원하는만큼 멤버를 선언할 수 있다. 단 구조체 선언은 어디까지나 구조체의 모양을 컴파일러에게 알리는 것뿐이므로 static, register같은 기억 부류를 지정한다든가 초기값을 줄 수는 없다.

구조체는 타입이 다른 변수들의 집합이지만 모든 멤버의 타입이 반드시 달라야만 하는 것은 아니다. 다음과 같이 타입이 같은 변수들도 하나의 구조체로 묶을 수 있으며 멤버를 하나만 가지는 구조체를 선언하는 것도 물론 가능하다.

 

struct

{

     int x,y;

} Point;

 

이 구조체는 좌표를 표현하는데 좌표는 x축, y축 두 개의 정수값으로 구성된다. 두 멤버의 타입이 같으므로 int Point[2];라는 배열로도 좌표를 표현할 수 있다. 그러나 배열을 사용하면 어느쪽이 x값이고 어느 쪽이 y값인지 각 첨자의 의미를 직접 지정해야 하고 실수할 위험이 많지만 구조체로 선언하면 멤버에 이름이 부여되기 때문에 훨씬 더 사용하기 쉽고 읽기도 쉽다.

 

gotoxy(Point[0], Point[1]);

gotoxy(Point.x, Point.y);

 

보다시피 배열은 0이 x고 1이 y라는 것을 외워야 하지만 구조체는 멤버의 이름으로 참조하므로 훨씬 더 의미 파악이 자연스럽다. 또한 구조체는 배열에 비해 함수의 인수로 전달하거나 리턴이 가능하므로 관리하기도 쉽다.