C언어 study_구조체

민성철·2022년 11월 23일
0

nadocoding_study_C

목록 보기
15/17

구조체

새로운 자료형 변수

이전 마지막 게시글에서도 작성되었던 구조체에 대해서 좀 더 알아보겠습니다.

이전 게시글에서는 #include(전처리기 지시문)을 통해 <sys/time.h> 함수 내의 정의되어 있는 timeval이라는 구조체를 사용했습니다.
(C언어의 #include와 python언어의 import는 각 언어의 내장 함수를 사용하기 위해 부르는 코드 같은데.. 이게 맞는 건지는 좀 더 공부해 봐야겠습니다..)

struct(구조체)는 같은 형태이지만 자료형이 다른 변수를 따로따로 저장해야 되는 번거로움을 보완하기 위해 여러 자료형의 변수를 묶어 하나의 새로운 자료형으로 정의하도록 만들 수 있습니다.
따라서, struct(구조체)는 사용자가 직접 정의할 수 있기 때문에 "사용자 정의 자료형(UDT, User-defined Data Type)"라고 합니다.

  • 구글의 C++ 코딩 스타일 가이드(https://google.github.io/styleguide/cppguide.html)에 따르면 구조체명은 단어의 첫 글자를 대문자로 적는 파스칼 표기법(pascal case)을 권장합니다.
    비슷한 표기법으로 카멜 표기법(camel case)이 있으며, 둘의 차이점은 파스칼 표기법은 모든 단어의 첫 알파벳을 대문자로 표기하고 카멜 표기법은 첫 단어를 제외하고 대문자로 표기합니다.
    또 다른 표기법으로 스네이크 표기법(snake case)가 있으며, 이는 언더바(_)를 활용하여 각 단어를 이어줌으로 가독성을 가집니다. (스네이크 표기법은 파이썬에서 주로 활용합니다.)

우선 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;
profile
ENTJ-A

0개의 댓글