c언어 구조체 / 구조체 배열과 포인터

이번에는 c언어의 구조체에 대해서 공부해보는 시간을 가져보겠습니다. 구조체는 변수선언, 배열, 포인터를 모두 공부했다면 사용법이 크게 다르지 않아 쉽게 이해하실 수 있으실 것 같습니다. 

 

구조체(structure)란?

Structure의 뜻은 구조, 구조물, 건축물, 체계 라는 뜻을 가지고 있습니다. 이 처럼 c언어에서의 구조체는 하나 이상의 변수들을 그룹으로 묶어 새로운 형태의 구조로 표현시키는 것입니다.  

 

예를들어 학생을 관리하는 프로그램이 있습니다. 한명의 학생을 관리하기 위해서는 어떤것들이 필요할까요?

문자 : 학교명, 이름, 수업받는 과목
숫자 : 학년, 반, 번호, 성적

만약 학생을 관리한다면 학생의 정보에는 {학교명, 학년, 반, 번호, 이름 등등}의 각각 다른 타입의 자료형으로 데이터를 한번에 저장해야 합니다. 지금까지는 "성적입력 : 10 20 30 50 40 " 등으로 하나의 자료형에 데이터를 집어넣는 방법으로 공부했습니다. 하지만 구조체를 활용하면 이러한 변수들을 묶어 표현할 수 있는 새로운 자료형을 만들 수 있습니다. 이를 두고 "사용자 정의 자료형" 이라고 이야기 합니다. 

 

#include <stdio.h>

struct student {   // 구조체 선언!
	char school[20];         //학교명
	int s_year;              // 학년 
	int s_class;             // 반
	int s_idx;                // 번호
	char name[20];           // 이름 
};

void main(void)
{
	struct student stu;

	strcpy(stu.school, "티스토리 중학교");
	stu.s_year = 1;
	stu.s_class = 1;
	stu.s_idx = 32;
	strcpy(stu.name, "홍지군");

	printf("%s %d학년 %d반 %d번 %s 학생입니다. \n", stu.school, stu.s_year, stu.s_class, stu.s_idx, stu.name);

}

위에 소스의 구조체 선언문을 보겠습니다. main 함수 밖에서 학교명, 학년, 반, 번호, 이름을 저장할 수 있는 변수를 가지고 있는 구조체 함수 student를 선언했습니다. 

 

사용은 "struct 구조체명 구조체변수명;"으로 사용되는데 위에서 정의한 구조체의 이름은 student입니다. 이 구조체를 사용하기 위한 이름으로 stu를 선언했습니다. 

 

아래 소스를 보면 구조체 변수명 stu를 통해서  school, s_year, s_class 등등 구조체의 멤버에 대해서 접근하고 데이터를 입력하는 것을 볼 수 있습니다. 구조체의 각각의 멤버들에 접근하여 데이터를 집어넣는 방법을 활용할 수 있습니다. 

 

위의 소스코드를 실행시킨 결과입니다. 

 

구조체 변수를 생성하게 되면 "구조체 변수명.멤버"로 접근하여 사용할 수 있고 배열과 동일하게 선언과 동시에 초기화를 시킬 수 있습니다. 

 

구조체 변수의 초기화
struct student {   // 구조체 선언!
	char school[20];         //학교명
	int s_year;              // 학년 
	int s_class;             // 반
	int s_idx;                // 번호
	char name[20];           // 이름 
};

  위 소스처럼 student라는 구조체를 선언하고 구조체를 초기화 하는 방법에 대해서 살펴보겠습니다. 

 

void main(void)
{
	struct student stu = { "티스토리 중학교",1,1,32,"홍지군" };

	printf("%s %d학년 %d반 %d번 %s 학생입니다. \n", stu.school, stu.s_year, stu.s_class, stu.s_idx, stu.name);

}

구조체 변수를 사용해 초기화 시킬때 배열의 초기화 방법과 동일하게 순서에 맞춰 데이터를 입력하는 방법이 있습니다. 

 

void main(void)
{
	struct student stu = { .school = "티스토리 중학교",.s_year=1, .s_class=1, .s_idx=32, .name="홍지군"};

	printf("%s %d학년 %d반 %d번 %s 학생입니다. \n", stu.school, stu.s_year, stu.s_class, stu.s_idx, stu.name);

}

또는 초기화 시킬 구조체 멤버를 지정하여 초기화 하는 방법또한 가능합니다. 

 

구조체 배열

배열은 같은 형태(자료형)의 많은 데이터를 반복해서 처리할때 쉽고 빠르게 하기 위해서 사용한다고 공부했습니다. 구조체 또한 새로운 자료형을 만든것이기 때문에 이러한 자료형을 배열로 사용할 수 있습니다. 

 

#include <stdio.h>

struct student {   // 구조체 선언!
	char school[20];         //학교명
	int s_year;              // 학년 
	char name[20];           // 이름 
};

void main(void)
{
	struct student stu[3];

}

 소스를 조금 더 짧게 학교명, 학년, 이름을 저장할 수 있는 구조체 student를 만들어봤습니다. 

구조체의 배열 선언은 일반 배열을 선언할때와 동일한 방법으로 변수명 뒤에 []를 사용해 배열의 크기를 지정해주는 방법이 있습니다. 

 

void main(void)
{
	struct student stu[3];

	strcpy(stu[0].school, "티스토리 대학교");
	stu[0].s_year = 1;
	strcpy(stu[0].name, "홍지군");
	

	printf("%s %d 학년 %s", stu[0].school, stu[0].s_year, stu[0].name);

}

 일반 배열의 선언과 사용법과 동일하게 사용하면서 뒤에 멤버연산자 . 를 사용해 멤버를 지정하여 값을 입력할 수 있습니다. 

 

구조체 포인터
#include <stdio.h>

struct student {   // 구조체 선언!
	char school[20];         //학교명
	int s_year;              // 학년 
	char name[20];           // 이름 
};

void main(void)
{
	struct student stu = { "티스토리 대학교",1,"홍지군" };     //구조체 변수 stu
	struct student* pstu;                     //  구조체 포인터 변수 pstu

	pstu = &stu;      

	printf("학교명: %s, 반 %d, 이름 : %s \n",pstu->school,pstu->s_year,pstu->name);
}

 구조체 또한 포인터변수를 사용할 수 있습니다. 만약 구조체 변수 stu를 선언하고 구조체 포인터 변수 pstu를 선언한뒤에 "pstu = &stu;" 로 pstu에 stu의 주소값을 대입합니다! 이렇게 되면 구조체 포인터 변수 pstu에는 구조체 변수 전체를 가리키게 됩니다. 

 

printf 함수 중 pstu -> school 에서 -> 연산자는 (*pstu).school 과 동일합니다. 

 

 구조체 변수의 멤버 접근 방법으로 stu.school 방법을 사용했었는데 구조체의 포인터에서 pstu -> school을 사용한 이유! 

 구조체의 멤버의 접근방법은 . 을 활용하여 접근이 가능한데 포인터 변수의 경우 *을 사용해 포인터임을 명시해야 합니다. *을 사용하게 될 경우 *연산자가 . 연산자보다 우선 순위가 낮아 엉뚱한 문장이 만들어지게 되어 ()를 활용해 (*pstu).school 로 선언해 주어야 합니다. 

하지만 매번 ()를 넣을 필요 없이 -> 연산자를 활용하는 방법으로 예제를 만든 것입니다. 

댓글

Designed by JB FACTORY