본문 바로가기

Programming/C & C++

Visual Studio - #pragma once, #ifndef, PCH 차이

 

#pragma once와 #ifndef 와 pch 세가지 다 중복으로 헤더 파일을 읽지 않도록 하는 것들이다

( #pragma once 는 지시자, #ifndef 는 전처리기 지시문, pch는.. 컴파일러 옵션? )

하나의 헤더파일을 여러 파일에서 include 할 경우 충돌이 나거나, 느려지는 경우가 있다. 이런 경우를 막기 위해서 위의 3가지 방법을 사용한다.

 

먼저 #pragma once의 사용법을 간단히 설명하자면

// PragmaOnce.h

#pragma once

#include <stdio.h>
#include <windows.h>
#include <vector>
#include <iostream>
#include <time.h>
#include <assert.h>

....

#pragma once는 컴파일러 전처리기 지시자로 한번 인식한 후 다음에는 어느 파일에서 include 해도 읽지 않고 바로 패스 한다.(다중 포함 최적화 라고도 한다)

( 자세한 설명은 https://docs.microsoft.com/en-us/cpp/preprocessor/once?view=msvc-170 참고 )

 

once pragma

Learn more about: once pragma

docs.microsoft.com

 

 

다음은 #ifndef ~~의 사용법이다.

// Ifndef.h

#ifndef __IFNDEF_H__ // __IFNDEF_H__ 라는 매크로가 정의가 안되어 있으면 진입한다.
#define __IFNDEF_H__ // 여기서 __IFNDEF_H__를 정의한다.

class TestClass
{
    TestClass();
    ~TestClass();
    
    .....
}

#endif	
// #ifndef와 한 쌍으로, "__IFNDEF_H__라는 매크로가 정의되어 있지 않으면.." 이라는 조건이 이곳에서 닫힌다.

이 방법은 include guard라고 한다 (https://en.wikipedia.org/wiki/Include_guard)

#ifndef 는 주석에서 간단하게 설명한것처럼 "특정 매크로가 선언되어 있지 않을 경우" 에 #ifndef 하단에 있는 코드를 진행시킨다.

( #ifndef에서의 n이 !이다. 즉 #ifdef는 "선언되어 있으면" 인것이고, #ifndef 는 굳이 표현하자면 !( ifdef ) 정도? )

이 방식을 사용할때 주의해야할 점은, Visual C++ 5.0 이상에서만 사용해야할 것, 그리고 사용하는 매크로가 이미 정의되어 있는 것은 아닌지 확인한 후 진행해야 한다는 점이다.

 

마지막으로 PCH.

두 군데에서 설정을 해야한다.

미리 컴파일 시킬 파일의 속성 - C / C++ 에서 미리 컴파일된 헤더를 찾아서 설정값을 Create

해당 파일이 속해있는 프로젝트의 속성 - 동일하게 C / C++에서 미리 컴파일된 헤더를 찾아서 Use로 바꿔두면 된다.

 

미리 컴파일된 헤더를 사용하게 되면 첫 컴파일때는 좀 느릴수는 있지만(pch 설정한 파일이 무겁다면..)

컴파일이 완료되면 해당 파일은 ###.pch로 생성되며, 그 이후 컴파일때는 첫 컴파일때보다 빠르다.

 

더보기

지극히 개인적인 생각으로는

pch > pragma once > ifndef 순으로 빠르지 않을까라는 생각이 든다 (물론 기껏해봤자 몇 ms 차이겠지만)

pch는 첫 컴파일 이후에는 아예 컴파일 목록에 추가가 되지 않고

(*물론 해당 파일이 수정되었을 경우 다시 컴파일 하거나, 에러를 띄우는 경우가 있다)

#pragma once 는 매번 컴파일 할때마다 작동되지만, 첫번째 해당 파일을 읽었을 경우 그 이후에는 패스

#ifndef 방식은,  어찌됬든 해당 파일은 열긴 여니까.. 하는 생각이 든다.