wn42
코딩이랑 이것저것
wn42
전체 방문자
오늘
어제
  • 분류 전체보기 (113)
    • 프로그래머스 (23)
      • LV1 (11)
      • LV2 (1)
      • LV3 (3)
      • 연습 (8)
    • 딥러닝 공부 (0)
      • 머신러닝&딥러닝 이론 (0)
    • 임베디드 (17)
      • Adventure Design (1)
      • 센서기반모바일로봇 (5)
      • ROS (9)
      • Google Coral (2)
    • C++ (38)
      • C++ 기초 (34)
      • 자료구조 및 알고리즘 (4)
    • Python (14)
      • 기본 파이썬 문법 (6)
      • Python 기초 (8)
    • 빅데이터 (9)
      • 빅데이터 첫걸음 시작하기(국비지원) (5)
      • 빅데이터 공부 (4)
    • 알고리즘 공부 (2)
      • 기본 알고리즘 (2)
    • 전자공학 (10)
      • 반도체 공정 (3)
      • 무선데이터통신 (7)
      • 반도체공학 (0)
    • C# (0)
      • C# 기본 (0)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • K디지털크레딧
  • 스택
  • stl
  • 데이터분석
  • 소멸자
  • 내일배움카드
  • numpy
  • c++
  • 프로그래머스
  • 정렬
  • google coral
  • 바이트디그리
  • 클래스
  • 딥러닝
  • 빅데이터 첫걸음 시작하기
  • Python
  • 변수
  • 조건문
  • 빅데이터
  • 스택/큐
  • 패스트캠퍼스
  • 인스턴스
  • 파이썬
  • ROS
  • 노드
  • 상속
  • 반복문
  • 데이터분석 인강
  • Queue
  • 큐

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
wn42

코딩이랑 이것저것

C++/C++ 기초

[C++] 매크로 / 인라인

2022. 12. 29. 16:39

 매크로 

컴파일러가 컴파일을 시작하기 전에 #define으로 정의된 상수를 매크로 확장 문자열로 변환하여 사용하는 것

  • 프로그램의 가독성이 높아지고, 유지보수가 용이해진다.
  • 매크로 확장 문자열에는 공백을 포함할 수 없다.
  • #define은 전처리 과정에서 치환되므로 메모리 공간에 할당되지 않는다. ▶ 주소 접근이 불가능하다.

 

매크로 상수

  • 매크로 상수는 다음과 같이 정의한다.
#define 매크로이름 값    // 전처리기 문의 끝에는 ;(세미콜론)을 붙이지 않는다.

 

매크로 상수 예제

#include <iostream>
#define PI 3.14159     // 매크로 상수 정의
using namespace std;


int main() {
	double radius = 5;

	cout << "PI: " << PI << endl;
	cout << "원의 넓이: " << PI * radius << endl;
	return 0;
}
PI: 3.14159
원의 넓이: 15.708
  • 3.14159를 PI라는 식별자로 변환하여 사용하였다.

 

#ifdef

  • 매크로가 정의되어 있는가 아닌가에 따라서 코드를 포함할지 말지 결정하는 전처리기 명령 ▶ 조건부 컴파일
  • #ifdef와 #endif 사이에 코드를 작성한다.
  • define 되는 것이 무엇이냐에 따라 간단히 무엇을 컴파일할 것인지를 나타낼 때 유용히 사용된다.
#include <iostream>
#define A
using namespace std;


int main() {
#ifdef A	// A가 정의되었으므로 아래의 코드를 포함
	cout << "Define_A" ;
#endif
#ifdef B	// B는 정의되지 않으므로 아래의 코드를 포함하지 않음
	cout << "Define_B";
#endif
	return 0;
}
Define_A

 

  • #else를 사용할 수 있다.
#include <iostream>
#define B
using namespace std;

int main() {
#ifdef A
	cout << "Define_A";
#else
	cout << "Define_B";
#endif
	return 0;
}
Define_B

 

 

매크로 함수

  • 매크로를 이용하여 #define에 인수로 함수의 정의를 전달함으로써, 함수처럼 동작하는 매크로 함수를 만들 수 있다.
  • 일반함수와 달리 단순 치환만 하기 때문에 일반 함수와 완벽히 똑같이 동작하지는 않는다. ▶ 인수 타입 신경 X
  • 매크로 함수를 사용하여 여러 개의 명령문을 동시에 포함할 수 있다.
  • 함수 호출에 의한 성능 저하가 발생하지 않고, 프로그램 실행속도가 빨라진다.
  • 정확한 함수의 구현이 어려운 탓에 디버깅이 어렵고, 함수 크기가 클수록 가독성이 떨어진다는 단점이 있다. ▶ 따라서 크기가 비교적 작은 간단한 함수를 대체하는 데 사용하는 것이 좋다.

 

매크로 함수 만들기

  • 매크로 함수는 다음과 같이 정의한다.
#define 함수명(인자) 치환식

 

Ex) 제곱 함수

#include <iostream>
#define square(x) x * x	// 매크로 함수 정의
using namespace std;

int main() {
	cout << square(3) << endl;
	return 0;
}
9
  • square라는 이름의 매크로 함수를 생성하였고, 인자로는 x를 받는다. 그리고 인자 x를 x*x로 치환한다.
  • 여기서 매크로 함수는 컴파일 되기 전에 전처리기에 의해 3*3으로 치환된다.

 

매크로 함수 유의점

#include <iostream>
#define square(x) x * x	// 매크로 함수 정의
using namespace std;

int main() {
	cout << square(3 + 1) << endl;
	return 0;
}
7
  • square 함수는 제곱 기능을 하기 때문에 3 + 1 = 4의 제곱인 16이 나올 것 같았지만 7이 나왔다.
  • 이는 전처리기에서 square(3 + 1)이 다음과 같이 치환되었기 때문이다.
x * x = 3 + 1 * 3 + 1 = 3 + 3 + 1 = 7
  • 3 + 1을 계산하기도 전에 x = 3 + 1로 치환하였기 때문에 7이라는 결과가 나타났다.
  • 이런 경우에는 다음과 같이 바꿔 주어야 한다.

 

올바른 치환식

#include <iostream>
#define square(x) (x) * (x)
using namespace std;

int main() {
	cout << square(3 + 1) << endl;
	return 0;
}
16
  • 이 경우에는 전처리기에서 치환할 때, (3 + 1) * (3 + 1)로 처리되기 때문에 정답이 16이 나왔다.

 

전처리 지시자를 활용한 매크로 함수

Ex) #을 이용한 매크로 함수

#include <iostream>
#define printString(str) cout << #str;
using namespace std;

int main() {
	printString(Hello);
	return 0;
}
Hello
  • #은 어떠한 인자 앞에 붙으면 해당 인자를 문자열로 바꾸어 버린다.

 

Ex) ##을 이용한 매크로 함수

#include <iostream>
#define Comb(a, b) a ## b;
using namespace std;

int main() {
	int Comb(x, y);
	xy = 3;
	cout << xy << endl;
	return 0;
}
3
  • ##은 받은 인자들을 하나로 합치는 기능을 수행한다.
  • 위 코드에서는 x와 y를 합쳐 xy의 이름으로 int 자료형을 생성하였다.

 

 

인라인 함수

  • 호출될 때  일반적인 함수의 호출 과정을 거치지 않고, 함수의 모든 코드를 호출된 자리에 바로 삽입하는 방식의 함수
  • 이 방식을 이용하면 함수 호출 시간은 절약되나, 함수 호출 과정으로 생기는 여러 이점을 포기해야 한다.
  • 코드가 매우 적은 함수만을 인라인 함수로 선언하는 것이 좋음
  • 매크로 함수에서 소괄호를 적절히 사용하지 않아 발생하는 오류가 디버깅을 어렵게 만들었고, 이를 해결하기 위해 인라인(inline) 함수가 등장하였음.
  • 인라인 함수는 전처리기가 치환하는 매크로 함수와 달리 그보다 똑똑한 컴파일러가 알아서 보통의 함수처럼 연산 순서를 고려하여 치환한다.
  • 만약 이미 존재하는 함수와 이름이 같은 인라인 함수를 정의할 경우, 작업 비용이 적은 함수로 골라서 사용한다. 만약 인라인 함수의 비용이 더 클 경우 인라인 함수 구문은 무시된다.

 

인라인 함수 만들기

  • 인라인 함수는 다음과 같이 정의한다.
__inline datatype function명(인자) {/*실행구문*/;}

// 예시
__inline int square(int x) { return x * x; }

 

Ex) 제곱 함수

#include <iostream>
using namespace std;
__inline int square(int x) { return x * x; }    // 인라인 함수 정의

int main() {
	cout << square(3) << endl;
	return 0;
}
9
  • 만약 main에서 square 함수를 정의하였다면 함수가 저장된 메모리로 점프하고, 해당 함수의 결과를 반환하는 과정에서 시간이 오래 걸리게 된다.
  • 인라인 함수는 그러한 시간 소요를 줄이고자 아래와 같은 동작을 하도록 만든 기능이다.
cout << 3 * 3 << endl;

 

Ex) 인라인 함수는 컴파일러가 알아서 연산 순서를 처리

#include <iostream>
using namespace std;
__inline int square(int x) { return x * x; }

int main() {
	cout << square(3 + 1) << endl;
	return 0;
}
16
  • 인라인 함수는 매크로 함수처럼 () 소괄호를 고려할 필요 없이 컴파일러가 알아서 연산을 보통의 함수처럼 처리한다.
    'C++/C++ 기초' 카테고리의 다른 글
    • [C++] 동적 메모리 할당
    • [C++] 레퍼런스(참조자)
    • [C++] void 타입 / main 함수
    • [C++] 변수 이해하기 (지역/전역/정적)
    wn42
    wn42
    코딩이랑 이것저것 하는 블로그

    티스토리툴바