// Main.c
// 구조체(structure) : 필요한 여러 자료형의 변수들을 한데 묶어서 하나의 자료형처럼 만들 수 있음
// struct 구조체명 예시 : struct Date
// {
// 자료형 멤버변수명; 예시 : int A;
// };
// . 연산자 : 구조체 멤버 접근 연산자.
// 구조체 : 설계도, 멤버 변수 : 부품, 구조체 변수 : 부품과 설계도로 만든 실제 물건
//
#include <stdio.h>
struct Date
{
// 무릇 ~라 하면 ~를 가지고 있다.
int Year;
int Month;
int Day;
// 자료형 멤버변수형;
};
void PrintBirthday(struct Date InBirthday); // 전방선언. 이 뒤에 PrintBirthday가 올테니 컴파일 오류를 일으키지 말라는 코드.
// 반환자료형 함수명(매개변수자료형(struct 구조체명) 매개변수명);
int main(void)
{
struct Date Birthday; // 사용자 정의 자료형 Date 변수 선언. 구조 : struct 구조체명 구조체 변수명;
Birthday.Year = 2024; //구조체 멤버 접근 연산자. 구조체 변수명.멤버변수명 = 값; Birthday 구조체 변수가 접근하고 있는 멤버변수의 값에 2024를 대입.
Birthday.Month = 1; //
Birthday.Day = 13;//
// 구조체 변수명.멤버변수명;
// Year; 와 같이 멤버변수만 사용하는 건 불가능하다. 무조건 구조체 변수명.멤버변수명으로 불러와야한다.
// Today.Year = 2026;과 같이 이름은 같은 멤버 변수지만 서로 다른 구조체 변수 안에 있다면 별개의 값이다.
// 구조체 변수 Birthday는 어느 메모리에 저장 될까요?.
// 당연하게도 스택 메모리입니다. 다른 기본 자료형과 마찬가지입니다.
// 초기화 하지 않으면 0이 아닌 쓰레기 값이 저장되어 있습니다.
PrintBirthday(Birthday);
return 0;
}
void PrintBirthday(struct Date InBirthday)
{
printf("%d/%d/%d\n", InBirthday.Year, InBirthday.Month, InBirthday.Day); //PrintBirthday(Birthday);로 해당 내용을 출력 후 반환되는 값이 없기에 void 반환자료형
}
// Main.c
#include <stdio.h>
struct Date
{
int Year;
int Month;
int Day;
};
void PrintBirthday(struct Date InBirthday);
int main(void)
{
struct Date Birthday; // 구조체 변수 Birthday의 값이 정해지지 않았기 때문?
// 따라서 Birthday.Year = 2026; 과 같이 값을 대입, 혹은 초기화 해야한다.
PrintBirthday(Birthday);
return 0;
}
void PrintBirthday(struct Date InBirthday)
{
printf("%d/%d/%d\n", InBirthday.Year, InBirthday.Month, InBirthday.Day);
}
// Main.c
// 챕터 9-2 : typedef
// typedef : type definition의 약자. 참조자(레퍼런스)와 같이 구조체의 별명을 지어줌.
struct Date
{
int Year;
int Month;
int Day;
};
typedef struct Date Date_t;
// typedef struct 구조체명 구조체별명
int main(void)
{
Date_t Birthday;
// 구조체의 별명을 통해 struct를 생략하고 구조체별명 구조체 변수로 넣을 수 있게 됨.
return 0;
}
// Main.c
// 초기화 방법
typedef struct Date
{
int Year;
int Month;
int Day;
} Date_t;
int main(void)
{
Date_t Today = { 0, };
/* 첫 번째 방법. */
Date_t Tomorrow = { 7, 7, 2021 };
// 구조체 별명 구조체 변수 = 값; 에서 값은 구조체 안의 멤버 변수 순서대로 대입된다. 이 경우 Year = 7, Month = 7, Day = 2021이 되버린다.
/* 두 번째 방법. 요소 나열법. 실수할 여지가 있으니 사용에 주의합시다. */
/* 나중에 누가 일,월,년 순으로 구조체 멤버변수 순서를 바꿔버리면 문제가 생길 수도 있습니다. */
/* const 멤버 변수를 선언해서 사용할때도 요소 나열법이 유용합니다. */
return 0;
}
// Main.c
#include <stdio.h>
struct Date // struct 구조체명으로 구조체 선언.
{
int Year; // 멤버변수
int Month;
int Day;
};
typedef struct Date Date_t; // typedef sturct 구조체명 구조체별명 으로 구조체의 별명(참조자)를 선언.
void IncreaseYear(Date_t InDate); // 전방 선언. 반환자료형 함수명(매개자료형 매개변수); void ~~ (struct Date InDate);로 적을 수도 있음.
int main(void)
{
Date_t Today; // 구조체별명 구조체 변수로 Today라는 구조체 변수를 선언. 혹은 struct Date Today;로 해도 됨.
Today.Year = 2021; // 구조체변수.(구조체멤버 접근 연산자)멤버 변수 = 값; 으로 이 구조체변수 내에 있는 멤버 변수인 Year에 2021을 대입시킴.
Today.Month = 5;
Today.Day = 26;
printf("%d/%d/%d\n", Today.Year, Today.Month, Today.Day);
IncreaseYear(Today);
printf("%d/%d/%d\n", Today.Year, Today.Month, Today.Day);
return 0;
}
void IncreaseYear(Date_t* InDate)
{
printf("IncreaseYear() has been called.\n");
++InDate.Year; // InDate는 어디까지나 구조체 변수 Today에서 값을 가져와서 InDate에게 대입시킨 것이기에 Today와 InDate는 별개의 함수로 분류된다.
return;
}
// Main.c
// 구조체로 가능한 포인터 자료형
#include <stdio.h>
struct Date // struct 구조체명 으로 구조체 선언
{
int Year; // 멤버 변수 선언
int Month;
int Day;
};
typedef struct Date Date_t; // typedef struct 구조체명 구조체 별명으로 구조체 별명 선언
void IncreaseYear(Date_t* InPtrToDate); // 전방 선언. 반환자료형 함수명(매개변수자료형 매개변수명); (매개변수자료형 매개변수명)에서 또는 (struct Date* InPtrToDate); 사용가능
int main(void)
{
Date_t Today; // 구조체 별명 구조체 변수;로 구조체변수 Today 선언. struct Date Today;도 가능.
Today.Year = 2021; // 구조체 변수.멤버 변수 = 값; 으로 구조체 변수 내에 있는 멤버 변수의 값을 초기화함.
Today.Month = 5;
Today.Day = 26;
Date_t* PtrToToday = &Today; // Today의 메모리 주소 값을 포인터 변수 Date_t의 PtrToToday의 메모리 주소 값에 대입시킨다.
printf("%d/%d/%d\n", Today.Year, Today.Month, Today.Day);
IncreaseYear(PtrToToday);
printf("%d/%d/%d\n", Today.Year, Today.Month, Today.Day);
return 0;
}
void IncreaseYear(Date_t* InPtrToDate)
{
printf("IncreaseYear() has been called.\n");
++(*InPtrToDate).Year;
return;
}
// Main.c
// 또다른 구조체 멤버 접근 연산자 '->'
// -> : 구조체 포인터에 역참조 연산자와 . 연산자를 합친 연산자가 -> 연산자. 괄호 없이도 사용 가능.
#include <stdio.h>
struct Date
{
int Year;
int Month;
int Day;
};
typedef struct Date Date_t;
void IncreaseYear(Date_t* InPtrToDate);
int main(void)
{
Date_t Today;
Today.Year = 2021;
Today.Month = 5;
Today.Day = 26;
Date_t* PtrToToday = &Today;
printf("%d/%d/%d\n", Today.Year, Today.Month, Today.Day);
IncreaseYear(PtrToToday);
printf("%d/%d/%d\n", Today.Year, Today.Month, Today.Day);
return 0;
}
void IncreaseYear(Date_t* InPtrToDate)
{
printf("IncreaseYear() has been called.\n");
//++(*InPtrToDate).Year;
// 위 코드와 아래 코드 기능적으로 동일함. ->를 사용하면 (), *, . 연산자를 사용할 필요가 없음.
++InPtrToDate->Year;
return;
}
// Main.c
// 여러 개의 반환 값 : 구조체를 함수 반환 자료형으로 쓰면 여러개의 값을 반환 가능하다.
#include <stdio.h>
struct Date
{
int Year;
int Month;
int Day;
};
typedef struct Date Date_t;
Date_t GetToday(void);
int main(void)
{
Date_t Today = { 0, }; // 구조체 변수 Today에 속해있는 멤버 변수 Year, Month, Day를 0으로 초기화한다.
printf("Today: %d/%d/%d\n", Today.Year, Today.Month, Today.Day);
Today = GetToday();// GetToday 함수로 반환받은 값을 Today에 대입시킨다. Year, Month, Day의 값이 GetToday 함수의 반환값에 대입되어 바뀐다.
printf("Today: %d/%d/%d\n", Today.Year, Today.Month, Today.Day);
return 0;
}
Date_t GetToday(void) // void가 아닌 구조체를 반환 자료형으로 써서 여러 개의 값을 반환할 수 있다.
{
printf("GetToday() has been called.\n");
Date_t Date;
Date.Year = 2020;
Date.Month = 7;
Date.Day = 7;
return Date; // 구조체 변수 Date에 있는 값을 메인 함수에 있는 GetToday()에 반환한다.
}
// Main.c
// 구조체 배열
#include <stdio.h>
struct Date
{
int Year;
int Month;
int Day;
};
typedef struct Date Date_t;
int main(void)
{
Date_t Anniversaries[3]; // 구조체 배열 Anniversaries을 선언하고 메모리 크기를 3 잡는다. 구조체 별명 구조체 배열[메모리크기], 또는 struct Date 구조체 배열[메모리크기]
size_t i, ElementSize;
Anniversaries[0].Year = 2000; // 배열 Anniversaries의 첫번째 메모리에 해당 값을 대입시킨다.
Anniversaries[0].Month = 1;
Anniversaries[0].Day = 1;
Anniversaries[1].Year = 2010; // 두번째 메모리에 해당 값을 대입시킨다.
Anniversaries[1].Month = 10;
Anniversaries[1].Day = 10;
Anniversaries[2].Year = 2020; // 세번째 메모리에 해당 값을 대입시킨다.
Anniversaries[2].Month = 20;
Anniversaries[2].Day = 20;
// Date_t Anniversaries, Date_t Anniversaries2 != Date_t Anniversaries[] 인 이유.
// Date_t Anniversaries, Date_t Anniversaries2는 다른 구조체 변수이기에 서로의 값을 별도의 과정 없이 공유받을 수 없다.
for (i = 0; i < 3; ++i)
{
printf("anniversaries[%zu]: %d/%d/%d\n", i, Anniversaries[i].Year,
Anniversaries[i].Month,
Anniversaries[i].Day);
}
printf("sizeof(anniversaries[0]): %zu\n", sizeof(Anniversaries[0]));
return 0;
}
// Main.cpp
// 챕터 9-3 : 구조체와 클래스
// Alt + shift를 누르고 여러 줄을 선택하면 동시에 수정할 수 있다.
#include <stdio.h>
#include <stdlib.h>
struct Human // 구조체
{
float Height; // 멤버 변수. 사람의 키
float Weight; // 사람의 몸무게
size_t Age; // 사람의 나이. 음수값이 적용되면 안되기에 size_t 변수타입으로 함.
void SayHello(void) // 사람이 말할 때 어떻게 말하나.
{
printf("Hello!\n");
return;
}
void SayMyInfo(void) // 사람이 자기소개 할 때 어떻게 자기소개를 하나.
{
printf("My Height is %.1f.\n", Height);
printf("My Weight is %.1f.\n", Weight);
printf("My age is %zu.\n\n", Age);
return;
}
// 위와 같이 객체 간의 상호작용에 중점을 둔 언어가 객체지향 프로그래밍 언어.
};
typedef struct Human Human_t;
int main(void)
{
Human_t* Park = (Human_t*)malloc(1 * sizeof(Human_t));
Park->Height = 173.f;
Park->Weight = 70.f;
Park->Age = 19;
Park->SayHello();
Park->SayMyInfo();
free(Park);
Park = NULL;
return 0;
}
// Main.c
// 챕터 9-4 : enum : 열거형(Enummeration)
// 구조체에서의 별명, 구조체 전용의 struct 나 참조자(레퍼런스)와 같음.
// 열거형 구조
// enum 열거형명
// {
// 멤버 변수
// };
// 열거형을 사용하면 불필요한 변수를 사용해서 메모리값이 잡아먹히는 일을 줄일 수 있다.
// 열거형 내에 들어가 있는 멤버 변수는 전부 값이 비례해서 대입되어 있다.
#include <stdio.h>
enum EMonth // enum 열거형명
{
MONTH_JAN = 1, // 멤버 변수
MONTH_FEB = 2,
MONTH_MAR = 3,
MONTH_APR = 4
};
enum EASCII
{
ASCII_A = 65, // 값이 다음 멤버 변수로 갈수록 ++1
ASCII_B, // 66
ASCII_C, // 67
ASCII_D // 68
};
int main(void)
{
printf("This month's(%d) lucky character is %c.", 3, 66);
// 갑자기 숫자 3과 66이 튀어나오면 이해가 안될 수 있습니다.
int March = 3, B = 66;
printf("This month's(%d) lucky character is %c.", March, B);
// 물론 위와 같이 하면 가독성이 좋아지긴 하나, 변수가 메모리 공간을 잡아먹음.
printf("This month's(%d) lucky character is %c.", MONTH_MAR, ASCII_B);
return 0;
}
// Main.c
#include <stdio.h>
enum ERole
{
ROLE_TOP,
ROLE_JUNGLE,
ROLE_MID,
ROLE_BOT,
ROLE_SUP
};
typedef enum ERole ERole_t;
typedef enum EChamp
{
CHAMP_LEESIN,
CHAMP_MASTER_LEE,
CHAMP_BLITZ_CRANK
} EChamp_t;
typedef enum
{
TIER_BRONZE,
TIER_SILVER,
TIER_GOLD
} ETier_t;
int main(void)
{
ERole_t MyRole = ROLE_SUP;
EChamp_t MyChamp = CHAMP_BLITZ_CRANK;
ETier_t MyTier = TIER_SILVER;
return 0;
}