메뉴 건너뛰기


Developer > Application

C,C++ C Extensions - inline function

2013.11.25 16:45

푸우 조회 수:11711

http://fateis.tistory.com/tag/C 에서 옮겨왔습니다.

서론

  • inline function은 gcc의 extension feature중의 하나다. 이에 대하여 알아보자.
  • 참고 문헌의 내용을 거의 그대로 번역하였으며 본인이 영어에 약간 부족함이 있는 관계로, 해당 번역이 약간 애매할 가능성이 있다.
  • 해석이 의미가 제대로 전달되지 않을 경우, 참고문헌의 URL 문서를 확인하라.

본론

* inline function을 선언함으로써, 당신은 caller의 코드에 해당 function의 코드를 통합화(integrate)되도록 GCC에 지정할 수 있다. 이것은 function call에 따른 오버헤드를 줄임으로써 실행을 훨씬 빠르게 할 수 있다. 게다가 실제 argument value 중 일부가 상수일 경우, 그 알려진 value가 모든 inline function의 코드가 caller의 코드쪽에 포함되지 않도록 컴파일 타임에서 평이화(simplifications)를 허용할 수 있다. 코드 사이즈에 대한 영향은 예측이 어렵다. 즉, 특별한 경우에 따라 Object code가 더 커질수도 있고, 작아질 수도 있다. function의 inline는 최적화(optimization)작업이고, 그것은 최적화 컴파일 작업에서만 효과를 본다. 만약 컴파일 시 -O 옵션을 사용하지 않으면 어떤 function도 inline되지 않는다.

* inline function은 ISO C99 standard에 포함되어있으나, GCC에서 구현한 것과는 많은 차이를 갖는다.

* inline function을 선언하기 위해서는, 아래처럼 function 선언 시 inline keyword를 추가한다.

inline int
inc(int *a)
{
    (*a)++;
}

* 만약 당신이 ISO C 프로그램들에 포함될 헤더를 작성한다면, inline 대신에 __inline__을 사용하라. (Alternate Keywords 참조) * 당신은 -finline-functions 옵션을 사용함으로써 모든 function를 간단하게 inline function을 만들 수 있다.

*function definition의 특정한 사용은 inline 치환(substitution)에 적합하지 않게 만들수도 있다. 이러한 것들 중에는 argument value의 사용, allocation의 사용, variable length data type(Variable length 참조)의 사용, compute된 goto(Lables as Values참조)의 사용, 또는 nested function(Nested function 참조)의 사용이 될 수 있다. -Winline 옵션을 사용함으로써 inline으로 명시된 function이 치환되지 않는 경우 및 실패의 이유에 대해 warning 메시지를 띄우게 할 수 있다.

* C++과는 다르게 C나 Objecttive-C에서 inline keyword는 function의 link에 영향을 끼치지 않음을 기억해라.

* GCC는 C++ program의 class body에 선언된 member function에서 명시적으로 inline으로 선언하지 않더라도 자동으로 inline화한다. ( -fno-default-inline 옵션으로 해당 기능을 무효화할 수 있다; http://gcc.gnu.org/onlinedocs/gcc-4.1.1/gcc/C_002b_002b-Dialect-Options.html#C_002b_002b-Dialect-Options Options Controlling C++ Dialet] 참조)

* function이 inline이고 static일때, 모든 function call이 caller의 코드에 통합화되고 그 fuction의 address가 한번도 사용되지 않았다면 그 function의 assembler code는 절대 참조되지 않는다. 이러한 경우에 GCC는 -fkeep-inline-functions 옵션을 명시하지 않았다면, 그 function에 대한 assembler code를 생성하지 않는다. 어떤 function call은 몇가지 이유로 통합화될 수 없다(특히, function의 선언보다 선행되어진 function call과 function의 선언안에서 recursive call을 할 경우에는 불가능하다.) 만약 통합화되지 않는 function call이 존재할 경우에는 그 function은 보통과 같이 assembler code를 생성한다. 또한 program이 그 function의 address를 참조한다면, 그 function은 inline화 될 수 없기 때문에, 보통과 같이 컴파일된다.

* inline function이 static이 아닐때, 컴파일러는 반드시 다른 소스 파일로부터 call이 있을꺼라 가정을 한다. 즉, global symbol이 program에서 단지 한번만 정의될 수 있기 때문에, 그 function은 다른 소스 file에서 정의되지 않아야하는데, 그 점에 있어서 통합화될 수 없다. 따라서, static이 아닌 inline function은 항상 일반적인 형태로 컴파일 되게 된다.

* function시 inline과 extern을 명시한다면, 그 정의는 inline될때 사용된다. 당신이 직접 address를 명시적으로 참조하도록 하지 않는다면, function이 스스로 컴파일 되는 경우는 없다. 그러한 address는 단순히 function만 선언한것 처럼, 외부 참조(external reference)가 되고, 정의되지 않는다.

이러한 inline과 extern의 조합은 대게 macro에 영향을 끼친다. 그것을 사용하는 방법은 function의 정의를 이런 키워드와 함께 헤더파일이 놓거나, 라이브러리 파일에 그 정의에 대한 다른 copy(inline과 extern을 제외)를 놓는 것이다. 헤더파일안의 이러한 정의는 대부분의 그런 function call을 inline시킬 것이다. 만약 function의 어떠한 사용도 남아있다면 그것은 라이브러리 안에 복사본을 참조할 것이다.

GCC가 결국 ISO C99의 inline function에 대한 semantic을 구현할 것이기 때문에, 호환성을 보장하기 위해서 static inline만을 사용하는 것은 훌륭한 것이다.(현재 존재하는 semantic은 -std=gnu89 옵션이 정의될 때 가능하도록 남게 될 것이나, 아직 구현되지 않았음에도 불구하고 결국 -std=gnu99 옵션이 default가 될 것이고, C99 semantic을 구현할 것이다.)

* GCC는 아래처럼 function의 속성에 always_inline을 명시하지 않았다면, optimizing하지 않을 때 어떤 function이라도 inline하지 않는다.

* Prototype.  */
     inline void foo (const char) __attribute__((always_inline));


결론

* 어떤 특정한 경우에 있어서는 inline이 올바른 해답도 아니며, 항상 inline 되지는 않는 다는 것을 기억해야 할 것이다.


참고 문헌