구조체
새로운 자료형 변수
이전 마지막 게시글에서도 작성되었던 구조체에 대해서 좀 더 알아보겠습니다.
이전 게시글에서는 #include(전처리기 지시문)을 통해 <sys/time.h> 함수 내의 정의되어 있는 timeval이라는 구조체를 사용했습니다.
(C언어의 #include와 python언어의 import는 각 언어의 내장 함수를 사용하기 위해 부르는 코드 같은데.. 이게 맞는 건지는 좀 더 공부해 봐야겠습니다..)
struct(구조체)는 같은 형태이지만 자료형이 다른 변수를 따로따로 저장해야 되는 번거로움을 보완하기 위해 여러 자료형의 변수를 묶어 하나의 새로운 자료형으로 정의하도록 만들 수 있습니다.
따라서, struct(구조체)는 사용자가 직접 정의할 수 있기 때문에 "사용자 정의 자료형(UDT, User-defined Data Type)"라고 합니다.
우선 sturct(구조체)를 정의하기 위해선 아래와 같습니다.
struct StudyInfo { // 구조체 정의
char * language; // 구조체 멤버 1
int year; // 구조체 멤버 2
int day; // 구조체 멤버 3
char * teaching; // 구조체 멤버 4
};
구조체를 정의했으니, 선언하여 사용해보는 코드는 아래와 같습니다.
struct StudyInfo fistStudy;
구조체의 변수 선언을 해줬으니, 정의해준 멤버의 값을 넣어보고 출력해보겠습니다.
(코드 생략)
fistStudy.language = "C_Language";
fistStudy.year = 2022;
fistStudy.day = 30;
fistStudy.teaching = "nadocoding";
printf("공부할 언어 : %s\n", fistStudy.language);
printf("공부한 연도 : %d\n", fistStudy.year);
printf("공부 기간 : %d 일\n", fistStudy.day);
printf("가르쳐 주는 사람 : %s\n", fistStudy.teaching);
(코드 생략)
output
공부할 언어 : C_Language
공부한 연도 : 2022
공부 기간 : 30 일
가르쳐 주는 사람 : nadocoding
구조체 자료형 변수의 멤버 값을 넣는 방법은 위 방법을 포함해 또 다른 방법이 있습니다.
이는 정의해준 멤버의 순서대로 중괄호를 이용해 값을 넣어주는 방법이며 아래 코드와 같습니다.
(코드 생략)
struct StudyInfo secondStudy = {"Python_Language", 2022, 60, "nadocoding"};
// 새로운 방법으로 멤버의 값을 넣어준뒤 출력해보겠습니다.
printf("공부할 언어 : %s\n", secondStudy.language);
printf("공부한 연도 : %d\n", secondStudy.year);
printf("공부 기간 : %d 일\n", secondStudy.day);
printf("가르쳐 주는 사람 : %s\n", secondStudy.teaching);
(코드 생략)
output
공부할 언어 : Phython_Language
공부한 연도 : 2022
공부 기간 : 60 일
가르쳐 주는 사람 : nadocoding
구조체
구조체 배열
구조체 변수와 일반 변수가 비슷하듯이, 구조체 배열은 일반 배열과 비슷합니다.
따라서, 배열 초기화와 비슷하게 하되 배열 크기의 따라서 중괄호로 나눠서 저장할 수 있습니다.
아래 예시 코드로 보겠습니다.
struct StudyInfo studyArray[2] = {
{"C_Language", 2022, 30, "nadocoding"},
{"Python_Language", 2022, 60, "nadocoding"}
};
구조체
구조체 포인터 사용
구조체 포인터는 이전에 배열 포인터와 비슷하게 구조체 변수의 주소를 가리키는 변수입니다.
포인터 변수 선언도 비슷하지만 주의할 점은, struct을 먼저 작성한 뒤에 구조체명과 변수명 사이에 *을 넣어줍니다.
struct StudyInfo * studyPtr;
studyPtr = &firstStudy;
위 코드에서 알 수 있듯이, 구조체 포인터 변수를 선언해줄 경우, 이를 출력할 때는 구조체 변수명 대신에 포인터 변수명을 넣어주면 포인터를 선언해준 구조체 변수의 멤버를 출력할 수 있습니다.
포인터 변수의 값을 출력하기 위해선 *을 사용해야 합니다.
하지만 주의할 점은, *studyPtr.language로 작성할 경우 *(studyPtr.language)로 인식하기 때문에 원하는 대로 활용할 수 없을뿐더러 에러가 발생합니다.
그렇기에 우선순위에서 먼저 인식이 되도록 (*studyPtr).language로 활용해야 합니다.
또 다른 방법으로는 화살표 (->)를 활용할 수 있으며, (*studyPtr).language와 같은 의미입니다.
여기서 화살표는 "**간접 멤버 참조 연산자**"라고 합니다.
이해를 돕기위한 예시 코드는 아래와 같습니다.
(코드 생략)
struct StudyInfo * studyPtr;
studyPtr = &firstStudy;
// fistStudy의 주소를 가리키는 포인터 변수를 활용하여 출력해보겠습니다.
printf("공부할 언어 : %s\n", (*studyPtr).language);
printf("공부한 연도 : %d\n", (*studyPtr).year);
printf("공부 기간 : %d 일\n", studyPrt -> day);
printf("가르쳐 주는 사람 : %s\n", studyPrt -> teaching);
(코드 생략)
구조체
이중 구조체(구조체 안에 구조체 사용하기)
구조체 포인터를 사용하여 기존 구조체 안에 똑같은 구조체를 다시 한번 정의할 수 있습니다.
그렇게 되면 동일한 구조체 변수가 여러 개일 경우, 기존 구조체 멤버의 구조체 포인터를 선언해준 뒤, 원하는 구조체 변수를 포인터 변수로 선언해주면 됩니다.
아래 예시 코드로 보겠습니다.
#include <stdio.h>
struct StudyInfo {
char * language;
int year;
int day;
char * teaching;
struct StudyInfo * studyGroup;
};
int main(void) {
struct StudyInfo firstStudy;
fistStudy.language = "C_Language";
fistStudy.year = 2022;
fistStudy.day = 30;
fistStudy.teaching = "nadocoding";
struct StudyInfo secondStudy = {"Python_Language", 2022, 60, "nadocoding"};
// secondStudy 구조체 변수 메모리 주소를 5번째 포인터 변수에 선언
firstStudy.studyGroup = &secondStudy;
printf("공부할 언어 : %s\n", fistStudy.studyGroup -> language);
printf("공부한 연도 : %d\n", fistStudy.studyGroup -> year);
printf("공부 기간 : %d 일\n", fistStudy.studyGroup -> day);
printf("가르쳐 주는 사람 : %s\n", firstStudy.studyGroup -> teaching);
return 0;
}
output
공부할 언어 : Phython_Language
공부한 연도 : 2022
공부 기간 : 60 일
가르쳐 주는 사람 : nadocoding
구조체
typedef로 구조체 선언하기
구조체 변수를 선언할 때 키워드와 구조체명을 모두 적어 넣습니다.
하지만 너무 길어질 수도 있기 때문에 이를 간략하게 typedef 키워드로 자료형을 간단하게 줄이는 방법입니다.
말이 복잡해 보일 수 있으나, 쉽게 말해 기존 자료형이나 구조체에 별명을 붙이고, 붙인 별명으로 대체해서 사용하는 것입니다.
이해를 돕기 위해 아래 예시 코드입니다.
typedef int 정수;
정수 학기 1;
typedef char 글자[];
글자 수업 = "컴퓨터";
typedef struct StudyInfo 프로그래밍;
프로그래밍 thirdStudy = {"Java_Language", 2023, 60, "nadocoding"}
printf("%d학기 %s 수업은 %s 입니다.\n", 학기, 수업, 프로그래밍.thirdStudy -> language);
output
1학기 컴퓨터 수업은 Java_Language 입니다.
위 방법 외에도 구조체를 정의할 때 별명을 붙이는 방법이 있습니다.
// 기존 구조체 (선언할 때 "StudyInfo"만 사용 가능)
struct StudyInfo {
char * language;
int year;
int day;
char * teaching;
struct StudyInfo * studyGroup;
};
// 구조체를 정의하며 별명을 붙이는 방법 (선언할 때 "StudyInfomation"과 별명인 "STUDY" 둘다 사용 가능)
typedef struct StudyInfomation {
char * language;
int year;
int day;
char * teaching;
struct StudyInfo * studyGroup;
}STUDY;
// 구조체를 정의할때 별명만 정의하는 방법 (선언할 때 "STUDY"만 사용 가능)
typedef struct StudyInfomation {
char * language;
int year;
int day;
char * teaching;
struct StudyInfo * studyGroup;
}STUDY;