Rylah's Study & Daily Life

Modern C++ : 03. C++ Build : PreProceccer - 프리프로세서 본문

Study/C++

Modern C++ : 03. C++ Build : PreProceccer - 프리프로세서

Rylah 2022. 2. 3. 16:09

PreProcessor : 프리프로세서

 - #include , #define, #ifdef, #pragma once

 

https://en.cppreference.com/w/cpp/preprocessor

 

Preprocessor - cppreference.com

The preprocessor is executed at translation phase 4, before the compilation. The result of preprocessing is a single file which is then passed to the actual compiler. [edit] Directives The preprocessing directives control the behavior of the preprocessor.

en.cppreference.com

 

Conditionally

#define ABCD 2
#include <iostream>

int main()
{

#ifdef ABCD // ABCD가 define이 되었나?
    std::cout << "1: yes\n";
#else
    std::cout << "1: no\n";
#endif

#ifndef ABCD // ABCD가 define 되지 않았나?
    std::cout << "2: no1\n";
#elif ABCD == 2 // ABCD == 2이나?
    std::cout << "2: yes\n";
#else
    std::cout << "2: no2\n";
#endif

사실 이 코드는 동작하지 않는 부분을 지우면 다음 코드와 같다.

#define ABCD 2
#include <iostream>

int main()
{
    std::cout << "1: yes\n";
    std::cout << "2: yes\n";

    return 0;
}

Preprocessor는 컴파일러에게 보내기 전에 코드 자체를 수정해준다.

 

Replace

#define MAX_UINT16 65535
#define MAX(a, b) (((a)>(b))? (a):(b))
#include <iostream>

int main()
{
	std::cout << 65535 << std::endl;
	std::cout << MAX_UINT16 << std::endl;
	std::cout << MAX(10, 100) << std::endl;
}

modern C++에서는 #define 사용을 지양하는 것이 좋다 (줄이는 것이 좋다.)

 

그렇다면 무엇을 써야할까?

 

algorithm 헤더에 있는 max stl 라이브러리를 사용하는 것이 더 안전한 코드 사용법이다.

 

또한 constexpr (C++17부터 GNU에서 사용가능)을 사용하는 것 또한 권장된다.

https://docs.microsoft.com/ko-kr/cpp/cpp/constexpr-cpp?view=msvc-170 

 

constexpr(C++)

C++ 언어 constexpr 키워드에 대한 가이드입니다.

docs.microsoft.com

#include <algorithm>
#include <iostream>
#include <limits>
constexpr int ABCD = 2;
int main()
{
	//std::cout << MAX_UINT16 << std::endl;
	//std::cout << MAX(10, 100) << std::endl;
	std::cout << std::numeric_limits<uint16_t>::max() << std::endl;
	std::cout << std::max(10, 100) << std::endl;

	if constexpr (ABCD)
	{
		std::cout << "1:Yes\n";
	}
	else
	{
		std::cout << "1:No\n";
	}

	std::cout << __FILE__ << std::endl;
	std::cout << __LINE__ << std::endl;
	std::cout << __DATE__ << std::endl;
	std::cout << __TIME__ << std::endl;

}

DATE, TIME은 컴파일한 시간을 나타내는 것이지 현재 실행 시간을 나타내는 것은 아니다.

__FILE__, __LINE__,  __DATE__, __TIME__, __linux__, __APPLE__, _MSC_VER 직접 하면서 알아보면 된다.

https://en.cppreference.com/w/cpp/preprocessor/replace

 

Replacing text macros - cppreference.com

The preprocessor supports text macro replacement. Function-like text macro replacement is also supported. [edit] Syntax #define identifier replacement-list(optional) (1) #define identifier( parameters ) replacement-list(optional) (2) #define identifier( pa

en.cppreference.com

 

아까전의 Cat 클래스 예제를 불러와본다.

 

 

헤더파일의 의미는 이렇게 복사붙여넣기를 클래스에 한 것과 동일하다.

 

 

유저 라이브러리는 따옴표 Standard는 <>

 

#include <string>
#include <vector>

// 헤더파일에서 include가 필요한 경우에는 이렇게 사용될 때 외에는 cpp에
class Cat
{
public:
	void speak();
private:
	std::vector<std::string> mFriends;
};

헤더파일에 include를 하는경우는 이렇게 std 라이브러리가 필요해서 쓰이는 경우 외에는 cpp에 하는 것을 권하지만

합의된 사항대로 하는 것이 좋다

 

//#ifndef CAT_H
//#define CAT_H
#pragma once // 이걸 쓰면 된다. 위 아래 3줄과 동일한 의미이다. 
             // pragma once
             // cat.h가 두번 정의되거나 할때 한번만 인식하게 하는 방법이다.
#include <string>
#include <vector>
class Cat
{
public:
	void speak();
private:
	std::vector<std::string>  mFriends;
};
//#endif

헤더파일을 다른 main.cpp에서 두번 선언하거나할때 방지하기 위해 #ifndef #define #endif로 처리해놓을 수 있다.

하지만 #pragma once로 처리할 수 있고 모든 헤더 파일에 #pragma once로 정의하면 쉽게 해결이 된다고 할 수 있다.

 

#define #ifdef => constexpr if , constexpr, c++ standard library

#include => Copy & Paste

            => 2번 이상 삽입되는걸 장비하기 위해 #pragma once 사용 추천

 

 

출처 : https://youtu.be/GUgX9eV_Bu0