2024.01.25(목)
하나 이상의 서로 다른 종류의 변수들을 묶어서 새로운 데이터 타입을 정의하는 것
struct Man {
int age;
char gender;
int id;
char name[11];
short int score;
};
struct Man man = { 19, 'M', 0x12345678, "Hong길동" , 100};
struct
키워드struct 구조체명
{
멤버1자료형 멤버1변수명; // <-- 구조체 멤버
멤버2자료형 멤버2변수명; // <-- 구조체 멤버
⁝
};
struct student
{
char name[10];
int age;
int height;
};
struct 구조체명 구조체변수명;
struct student st1;
struct 구조체명
{
멤버1자료형 멤버1변수명;
멤버2자료형 멤버2변수명;
⁝
} 구조체변수명;
struct student
{
char name[10];
int age;
int height;
} st1;
typedef
키워드struct
를 사용하여 구조체임을 명시해야 하나 typedef
키워드를 사용하여 구조체에 새로운 이름을 선언하면 매번 struct
키워드를 사용하지 않아도 됨typedef struct 구조체명 구조체별칭;
typedef struct student STUDENT;
typedef
선언을 동시에typedef struct (구조체명)
{
멤버1자료형 멤버1변수명;
멤버2자료형 멤버2변수명;
⁝
} 구조체별칭;
typedef struct // 구조체명 생략 가능
{
char name[10];
int age;
int height;
} STUDENT;
typedef struct _Man {
struct _Man *next;
struct _Man *prev;
char name[50];
int age;
char gender;
char tel[50];
} Man, *PMan;
typedef struct Man {
struct Man *next;
struct Man *prev;
char name[50];
int age;
char gender;
char tel[50];
} Man;
구조체변수명 = {.멤버1변수명 = 초깃값, .멤버1변수명 = 초깃값, …};
st1 = {.name = "조미연", .age = 26, .height = 161};
.
구조체변수명.멤버변수명
st1.name, st1.age, st1.height
STUDENT* ptr_st1 = &st1; // 구조체 포인터 ptr_st1
참조 연산자(*
) 사용
(*구조체포인터).멤버변수명
printf("%s", (*ptr_st1).name); // 조미연
화살표 연산자(->
) 사용
✔️일반적으로 많이 사용됨
구조체포인터 -> 멤버변수명
printf("%s", ptr_st1 -> name); // 조미연
구조체와 달리 모든 멤버 변수가 하나의 메모리 공간을 공유
struct stTemp {
char a;
int b;
double c;
} st;
union unTemp {
char a;
int b;
double c;
} un;
union
키워드를 사용하며 사용방법은 구조체와 동일데이터들을 열거한 집합
enum
키워드 사용enum 열거형명 {
값1 = 초깃값,
값2,
값3
};
enum DayOfWeek {
Sunday = 0,
Monday,
Tuesday,
Wednesday,
Thursday,
Friday,
Saturday
};
enum 열거형명 변수명;
typedef
키워드 사용 가능typedef enum (열거형명) {
값1 = 초깃값,
값2,
값3
} 열거형별칭;
열거형별칭 열거형변수명;
typedef enum _DayOfWeek {
Sunday = 0,
Monday,
Tuesday,
Wednesday,
Thursday,
Friday,
Saturday
} DayOfWeek;
DayOfWeek week;
메모리 | 설명 |
---|---|
코드 영역 | 실행할 명령어들이 저장되고 CPU가 명령어들을 하나씩 가져가 처리 |
데이터 영역 | 전역변수, static 변수가 저장됨 → 프로그램 시작과 동시에 할당, 종료되면 메모리 해제 |
힙 영역 (런타임에 크기 결정) | 동적 할당 영역 → 메모리 할당(malloc)과 해제(free)의 반복 |
스택 영역 (컴파일 타임에 크기 결정) | LIFO 방식, 지역변수, 매개변수, 포인터 등이 저장됨 |
stdlib.h
헤더 파일에 정의되어 있기 때문에 코드 상단에 #include <stdlib.h>
추가malloc
함수 사용void* malloc(size_t size);
size
: 바이트 단위void*
: 타입이 지정되지 않은 포인터 → 사용자가 type casting해서 사용(데이터타입*)malloc(sizeof(데이터타입)*할당크기);
형식으로 할당free
함수 사용void malloc(void* _Block);
malloc
으로 동적 할당한 메모리 해제#include <stdio.h>
#include <stdlib.h>
int main() {
int num;
int* student;
printf("학생수를 입력하세요: ");
scanf("%d", &num);
student = (int*)malloc(sizeof(int) * num);
if (student == NULL) {
printf("메모리가 할당되지 않았습니다.\n");
return 0;
}
printf("할당된 메모리 크기는 %dbyte입니다.\n", sizeof(int) * num);
free(student);
return 0;
}
Heap 메모리에 할당한 메모리는 Stack 메모리의 포인터 변수를 통해서만 사용 가능
앞으로 객체 기반에서 new
연산자를 이용한 객체 생성의 메모리 구조는 모두 위 형태 기반
🌟 반드시 메모리 할당 후 사용이 끝나면 해제해야 함!
그렇지 않으면 student 변수는 사라져도 Heap에 할당된 메모리는 그대로 남아 메모리 누수 발생💦
- 메모리 누수(memory leak)
컴퓨터 프로그램이 필요하지 않은 메모리를 계속 점유하고 있는 현상- 자바스크립트의 경우 garbage collector가 사용하지 않는 메모리를 알아서 처리해주기 때문에 걱정할 필요는 없음😋
우리가 우체국에서 물건을 어디론가 보낼 때, 물건의 종류, 무게, 높이 등의 정보를 입력한다. 우리는 이러한 정보들을 갖고 있는 물건에 대한 구조체를 만들어보자. 구조체 이름은 object라고 하고, 구조체 멤버로는 이름(name), 높이(height), 무게(weight)를 갖는다. 구조체 변수를 하나 선언하고, 구조체 변수를 통해 각각의 멤버에 값을 대입한다. 대입하는 값은 사용자로부터 입력 받으며, 입력이 끝나면 대입한 멤버의 값을 화면에 출력하도록 프로그램을 작성하라.
/******************************************************************************
출력 예)
물건의 이름: 책
물건의 높이(cm): 30
물건의 무게(kg): 2
보낼 물건의 정보: 책, 30cm, 2kg
*******************************************************************************/
#include <stdio.h>
struct object {
char name[50];
int height;
int weight;
};
int main() {
struct object user_object;
printf("물건의 이름: ");
scanf("%s", user_object.name); // 배열 이름 자체가 주소 (포인터 상수)
printf("물건의 높이(cm): ");
scanf("%d", &user_object.height);
printf("물건의 무게(kg): ");
scanf("%d", &user_object.weight);
printf("\n보낼 물건의 정보: %s, %dcm, %dkg\n", user_object.name, user_object.height, user_object.weight);
return 0;
}
#include <stdio.h>
// typedef 사용
typedef struct {
char name[50];
int height;
int weight;
} Object;
int main() {
Object user_object;
printf("물건의 이름: ");
scanf("%s", user_object.name); // 배열 이름 자체가 주소 (포인터 상수)
printf("물건의 높이(cm): ");
scanf("%d", &user_object.height);
printf("물건의 무게(kg): ");
scanf("%d", &user_object.weight);
printf("\n보낼 물건의 정보: %s, %dcm, %dkg\n", user_object.name, user_object.height, user_object.weight);
return 0;
}