[C] 16. 키워드(Keyword)

Wonder_Land🛕·2022년 8월 1일
0

[C]

목록 보기
17/18
post-thumbnail
  1. typedef 키워드
  2. #pragma 키워드
  3. Q&A
  4. 마치며

1. 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 STUDENTSTUDENT로 바꿔봅시다.

#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와 똑같아집니다.

상당히 편리하네용 😊


2. #pragma 키워드

  • #pragma 키워드
    : 컴파일러에게 말하는 전처리기 명령

#pragma는,
#include, #define과 같이 컴파일 이전에 처리되지만,
그 명령은 컴파일러에게 전달합니다.

#pragma는 컴파일러마다 다르고 통일된 것이 없습니다.

1) #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로 하면 됩니다.


2) #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가 두 번 정의되어 중복이 되기 때문입니다.

그렇다면 헤더 파일을 한 번만 포함시켜야 하는데,
이렇게 중복되는 상황을 어떻게 피할까요?

(1) 전처리기 명령 이용

/* 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로 복사됩니다.


(2) #pragmam once 키워드 이용

이 방법은 실제로 많은 헤더파일에서 사용되고 있으며,
(1)번 방법보다 훨씬 단순하게 할 수 있습니다.

/* weird.h */
#pragma once

struct Weird {
  char arr[2];
  int i;
};

ifndef보다 훨씬 단순하죠?

그리고 컴파일 시간도 절약할 수 있습니다.

ifndef를 사용하면, 전처리기가 해당 헤더파일을 직접 열어, WEIRD_H가 정의되었는지 확인해야합니다.

pragma once를 이용하면 한 번만 포함되었다면 헤더파일을 다시 열어보지도 않기 때문에,
컴파일 시간이 단축됩니다.

하지만, 컴파일러마다 #pragma키워드가 다를 수 있어 주의해야 합니다.


3. Q&A

-


4. 마치며

-

[Reference] : 위 글은 다음 내용을 참고, 인용하여 만들어졌습니다.

profile
아무것도 모르는 컴공 학생의 Wonder_Land

0개의 댓글