- typedef 키워드
- #pragma 키워드
- Q&A
- 마치며
typedef
키워드다음은 구조체를 활용한 예시입니다.
#include <stdio.h>
void print_Student(struct STUDENT s);
struct STUDENT {
char name[6];
int grade;
};
int main() {
struct STUDENT Alice = {"Alice", 1};
struct STUDENT Bob = {"Bob", 2};
print_Student(Alice);
print_Student(Bob);
return 0;
}
void print_Student(struct STUDENT s) {
printf("** Print %6s's information **\n", s.name);
printf("---------------------------------\n");
printf("Name : %s\n", s.name);
printf("Grade : %d\n", s.grade);
printf("---------------------------------\n");
}
[Result]
** Print Alice's information **
---------------------------------
Name : Alice
Grade : 1
---------------------------------
** Print Bob's information **
---------------------------------
Name : Bob
Grade : 2
---------------------------------
그런데....
구조체를 사용하다보면 귀찮은 점이 있습니다.
매번 struct 구조체이름
라는 키워드를 작성해줘야 합니다.
깜빡하면? 수 많은 오류문을 볼 수 있습니다...
이 때, 사용할 수 있는 방법이 typedef
키워드입니다.
- typedef 키워드
typedef 새로운이름 기존이름
위의 예시의 struct STUDENT
를 STUDENT
로 바꿔봅시다.
#include <stdio.h>
struct STUDENT {
char name[6];
int grade;
};
typedef struct STUDENT STUDENT;
void print_Student(STUDENT s);
int main() {
STUDENT Alice = {"Alice", 1};
STUDENT Bob = {"Bob", 2};
print_Student(Alice);
print_Student(Bob);
return 0;
}
void print_Student(STUDENT s) {
printf("** Print %6s's information **\n", s.name);
printf("---------------------------------\n");
printf("Name : %s\n", s.name);
printf("Grade : %d\n", s.grade);
printf("---------------------------------\n");
}
즉,
struct STUDENT Alice
는
STUDENT Alice
와 똑같아집니다.
상당히 편리하네용 😊
#pragma
키워드
- #pragma 키워드
: 컴파일러에게 말하는 전처리기 명령
#pragma
는,
#include, #define
과 같이 컴파일 이전에 처리되지만,
그 명령은 컴파일러에게 전달합니다.
#pragma
는 컴파일러마다 다르고 통일된 것이 없습니다.
#pragma pack
#include <stdio.h>
struct Weird {
char arr[2];
int i;
};
int main() {
struct Weird a;
printf("size of a : %d \n", sizeof(a));
return 0;
}
[Result]
size of a : 8
????
a
의 크기는 1바이트 char 2개, 4바이트 int 1개로 6바이트 아닌가요?
사실 메모리 상에서 위 구조체의 크기는 8바이트로 컴파일러가 지정했습니다.
우리가 사용하는 컴퓨터는 항상 4바이트 단위로 처리하는 것이 더 빠르기 때문에,
데이터들은 4의 배수로 데이터를 보관하는 것이 더 용이합니다.
이 처럼, 데이터가 4의 배수의 경계에 놓인 것을 '더블 워드 경계에 놓여 있다'라고 합니다.
따라서 위의 a
도 필요없는 저장 공간 2바이트가 추가 되어서 4의 배수인 8바이트가 저장된 것입니다.
이 때, 구조체를 더블 워드 경계에 놓지 말라고 할 때 #pragma
키워드를 사용합니다.
#include <stdio.h>
#pragma pack(1)
struct Weird {
char arr[2];
int i;
};
int main() {
struct Weird a;
printf("size of a : %d \n", sizeof(a));
return 0;
}
[Result]
size of a : 6
#pragma pack(1)
위의 문장은 "구조체를 1바이트 단위로 정렬하라"라는 뜻입니다.
1외에도 2, 4, 8, 16 등이 올 수 있습니다.
만약 기본값, 더블 워드 경계로 정렬하기 위해서는 4
로 하면 됩니다.
#pragma once
위의 예시에서 Weird
구조체를 다른 헤더 파일로 작성해봅시다.
/* weird.h */
struct Weird {
char arr[2];
int i;
};
/* test.c */
#include <stdio.h>
#include "weird.h"
int main() {
struct Weird a;
a.i = 3;
printf("Weird 구조체의 a.i : %d \n", a.i);
return 0;
}
[Result]
Weird 구조체의 a.i : 3
만약 test.c
에서, 실수로 weird.h
를 두 번 포함했다면?
컴파일 오류가 발생합니다.
sturct Weird
가 두 번 정의되어 중복이 되기 때문입니다.
그렇다면 헤더 파일을 한 번만 포함시켜야 하는데,
이렇게 중복되는 상황을 어떻게 피할까요?
/* weird.h */
#ifndef WEIRD_H
#define WEIRD_H
struct Weird {
char arr[2];
int i;
};
#endif
위의 헤더파일을 보면,
만약 WEIRD_H
가 정의되어 있지 않으면,
WEIRD_H
를 정의합니다.
/* test.c */
#include <stdio.h>
#include "weird.h"
int main() {
struct Weird a;
a.i = 3;
printf("Weird 구조체의 a.i : %d \n", a.i);
return 0;
}
test.c
에는 WEIRD_H
가 정의되어 있으므로,
#ifndef
가 참이 되어, #define WEIRD_H
가 수행되어 WEIRD_H
가 정의됩니다.
그리고 헤더파일의 내용도 test.c
로 복사됩니다.
#pragmam once
키워드 이용이 방법은 실제로 많은 헤더파일에서 사용되고 있으며,
(1)번 방법보다 훨씬 단순하게 할 수 있습니다.
/* weird.h */
#pragma once
struct Weird {
char arr[2];
int i;
};
ifndef
보다 훨씬 단순하죠?
그리고 컴파일 시간도 절약할 수 있습니다.
ifndef
를 사용하면, 전처리기가 해당 헤더파일을 직접 열어, WEIRD_H
가 정의되었는지 확인해야합니다.
pragma once
를 이용하면 한 번만 포함되었다면 헤더파일을 다시 열어보지도 않기 때문에,
컴파일 시간이 단축됩니다.
하지만, 컴파일러마다 #pragma
키워드가 다를 수 있어 주의해야 합니다.
-
-
[Reference] : 위 글은 다음 내용을 참고, 인용하여 만들어졌습니다.