출처 URL : http://kelp.or.kr/korweblog/stories.php?story=01/08/10/9978807
인라인 함수(inline function)
이 예약어를 함수명 앞에 사용하면 함수가 호출할 때마다 마치 매크로 확장인양 새로운 함수 코드 블럭의 복사본이란 놈이 함수가 호출된 위치에 쑤욱 삽입된다.
특징은 #define문을 사용하는 매크로의 부작용(side effect : 아래에 설명함)을 막아주고 둘째는 일반 함수를 호출할 때 걸리는 부하를 없애주기도 한다. 이놈은 매크로와 일반함수의 기능을 모두 갖는다.
그러나 함수의 코드 블럭이 여러 곳에 나타나기 때문에 실행 코드가 커지는 단점을 갖는다.
이제 inline함수가 어떤 모습을 했는지 아래를 보면 알 수 있다.
일반적인 cpp 함수
1 // inline.cpp
2
3 #include <iostream.h>
4
5 inline void print(void)
6 {
7 cout << "inline function code block\n";
8 }
9
10 int main(void)
11 {
12 print();
13 print();
14 return 0;
15 }
위의 소스코드를 컴파일하면 생성하는 어셈블리 코드를 살펴보면
아래와 같다.
; File c:\inline.cpp
; // inline.cpp
;
; #include <iostream.h>
;
; inline void print(void)
; {
; cout << "inline function code block\n";
; }
;
; int main(void)
; {
; Line 11입니다.
_main:
push bp
mov bp,sp
mov ax,OFFSET L01265
call FAR PTR __aFchkstk
push si
push di
; print();
; Line 12입니다.
push OFFSET??_C@_0BM@BGPN@inline?5
function ?5code?5block?6?$AA@
push OFFSET ?cout@@3Vostream_withassign @@A
call FAR PTR ??6ostream@@RACAAV0@PBD @Z
jmp L01260 L01260:
; print();
; Line 13입니다.
push OFFSET??_C@_0BM@BGPN@inline?5
function ?5code?5block?6?$AA@
push OFFSET ?cout@@3Vostream_withassign @@A
call FAR PTR ??6ostream@@RACAAV0@PBD @Z
jmp L01260:
L01260:
; return 0;
; Line 14입니다.
mov ax,OFFSET 0
jmp L01264
; } Line 15입니다.
L01264:
pop di
pop si
leave
ret OFFSET 0
; Local Size: 2
이렇게 변합니다...
Line12와 Line13을 보시면 어셈블리 코드가 삽입되어 있음을 볼 수 있습니다. 따라서 인라인 함수는 아주 작고 자주 호출되지 않는 경우에만 사용하는 것이 좋습니다. 만약, 함수가 inline으로 선언되어 있다고 하더라도 그 함수의 코드 블럭이 크다면 컴파일러는 인라인을 확장하지 않고 일반함수로 취급한다.
그러면 디바이스 드라이버 책으로 돌아가서 왜 많은 함수들을 헤더 파일안에 바로 inline 함수를 선언해 놓았을까?
바로 위에서 이야기한 #define문을 사용하는 매크로의 부작용(side effect)을 막아주고 둘째는 일반 함수를 호출할 때 걸리는 부하를 없애주기 때문이 아닐런지!!. 매크로의 장점과 함수의 장점을 가진듯한......
<이 장점을 살리기 위해 모듈 작성자는 컴파일 플래그에 -O를 명시해야 inline함수를
확장할 수 있습니다>
그러면 마지막으로 매크로의 부작용(side effect)에 대해 알아 보겠습니다.
매크로와 인라인 함수를 비교해보면 ...
//max.cpp
#include <iostream.h>
#define MAX(A,B) ((A) > (B) ? (A) : (B)) // ----> 매크로!!
inline int max(int a, int b) // -----> inline!!
{
if(a > b) // 23 > 45
return a; // 거짓
return b; // 참 45를 리턴
}
int main(void)
{
int i, x, y;
x = 23;
y = 45;
i = MAX(x++, y++); // --->side effcet!!!! 매크로의 부작용
// x = 24, y = 47
cout << "x = " << x << ", y = " << y
<< ", i = " << i << "\n";
x = 23;
y = 45;
i = max(x++, y++); // --->inline i에는 리턴받은 45가 되고 x와 y는 1씩 증가
// x = 24, y = 46이 된다
cout << "x = " << x << ", y = " << y
<< ", i = " << i << "\n";
return 0;
}
이프로그램의 실행 결과는 다음과 같다.
x = 24, y = 47, i = 46 ---> 매크로
x = 24, y = 46, i = 45 ---> inline
매크로로 실행시 전혀 예상치 못한 값이 나왔음을 알 수 있다.
매크로를 살펴보면
i = ((x++) > (y++) ? (x++) : (y++)); 와 같이 되며
x와 y를 비교할 때 현재 x는 23이고, y는 45이므로 조건식은 거짓이 된다. 조건이 판별이 된 후 x와 y는 각각 1씩 증가하며 x와 y의 값은 각각 24와 46이 된다. 조건 판단 결과가 거짓이므로 (y++)을 리턴하며 현재 y의 값은 46이므로 MAX 매크로는 46을 리턴한다. 다음에 y는 다시 1이 증가하여 y값은 47이 된다
그리고 (x++)는 참일 때만 실행하므로 조건이 실행 안되므로 그대로 24가 된다. 이렇게 매크로의 치환은 전혀 엉뚱한 값이 나오는데 이것이 바로 side effect이다. inline함수를 사용하면 이런 부작용을 막을 수 가 있다.
'Robotics > Software Tech.' 카테고리의 다른 글
[MFC] 쓸만한 2D 그래프 컨트롤 (0) | 2008.10.31 |
---|---|
XML 파서의 종류, DOM과 SAX (0) | 2008.10.27 |
디버그뷰(Debug View)의 활용 (0) | 2008.10.17 |
Visual Studio C++ 키 바인딩 테이블 (0) | 2008.10.17 |
MFC DLL (0) | 2008.09.22 |