inline함수 어떻게 쓰는 것이 옳은 건가요?

송지석의 이미지

inline 함수를 별 생각 없이 사용하다가, 문득 궁금한 것이 생겼습니다.

제가 사용할 때 inline 함수를 C 파일에 정의해놓고, 헤더파일에 선언해서 외부에서는 헤더만 보고 쓰곤 했거든요.

util.c

__inline__ void MyInline( void )
{
    some code...
}

util.h__inline__ void MyInline( void );

이렇게 해놓고 main.c 같은 파일에서 이 함수를 갖다 쓰면 inline 속성이 없어지나요?
어디 볼만한 문서가 있을 지,, 가르쳐주세요.

aqwerf의 이미지

가장 일반적인 방법은 header file이나 source file에

static __inline__ void MyInline( void )
{
    some code...
}

처럼 사용하는 것 입니다. 이렇게 해야 완전히 inline 되었다고 할 수 있죠.

설명은 gcc manual을 보면 어느 정도 이해 할 수 있습니다.
http://gcc.gnu.org/onlinedocs/gcc-3.4.1/gcc/Inline.html#Inline
다른 compiler를 사용한다면 해당 컴파일러의 manual을 보는 것이 좋습니다. 조금씩 차이가 있고 실제로 여러 제약이 있으므로 정확히 사용하려면 꼭 읽어보셔야 합니다.

gcc라면 -Winline option을 compile시에 주어 inline이 되었나 확인을 해봐도 되고요.
gcc -S option을 주거나, objdump를 이용하여 assembly 언어로 뽑아서 직접 확인하는 것이 가장 확실하죠..

몰론 이 경우 optimization을 켜놓거나 inline이 되도록 compile option을 반드시 주어야 합니다.

voider의 이미지

책에 이렇게 써있네요
- inline 함수 정의는 그것을 호출하는 어떠한 함수보다 앞에 있어야 한다

여기에서 함수 정의 라는 말이 나오죠?
그렇다면 소스 파일에다가 inline 을 정의한후 다른 소스 파일에서 그 함수를
사용하는것은 올바르지 않습니다

static 은 인라인에 꼭 붙어야 한다고 생각이 안드네요...

-- 아쉬운 하루 되세요 --

aqwerf의 이미지

voider wrote:
그렇다면 소스 파일에다가 inline 을 정의한후 다른 소스 파일에서 그 함수를 사용하는것은 올바르지 않습니다

static 은 인라인에 꼭 붙어야 한다고 생각이 안드네요...

gcc에서는 static을 붙이지 않은 경우 다른 파일에서 참조도 가능합니다. 물론 이 경우에는 일반 함수와 동일하죠. 위에 링크되어 있는 도움말을 참조하세요.

실제 사용 시 static을 사용하나 않하나 같은 파일내에서의 inline 기능은 동일합니다. 단, static을 붙이지 않은 경우에는 함수도 추가로 만들어지게 됩니다.
이와 같이 되면 불필요한 code가 생기는 셈이죠. 물론 일부러 이렇게 되기를 원한다면 몰라도 대부분은 이와 같은 기능은 원치 않을 겁니다. 그리고 이렇게 함수가 만들어지면 다른 소스내의 함수와 이름이 중복될 수 있어 link시 에러가 발생할 수 있습니다.
이렇기 때문에 gcc에서는 항상 static을 붙이는 것이 바람직합니다.

실제로 확인하려면 다음과 같은 code에서 static이 있는 경우와 없는 경우를 어셈블러로 뽑아보세요..

static __inline__ int test(void)
{
     return 1;
}

int main()
{
    int i;
    i = test(); 
    return i;
}

이를 다음과 같이 실행하면 됩니다.
gcc -S -O2 test.c

결과를 보면 static이 없는 경우에는 어셈블러에서 다음과 같이 test라는 함수가 추가로 정의가 됩니다.

test:
        pushl   %ebp
        movl    $1, %eax
        movl    %esp, %ebp
        popl    %ebp
        ret
hellworld의 이미지

현재 gcc 버전 7.4.0 기준으로 inline 키워드만 쓰면 undefined function 에러가 납니다.
그래서 static 키워드나 extern 키워드 둘 중 하나는 무조건 붙어야해요.

Stephen Kyoungwon Kim@Google의 이미지

https://stackoverflow.com/questions/25000497/whats-the-difference-between-static-inline-extern-inline-and-a-normal-inline-f

무조건 붙어야 하는 것은 아닌 것 같습니다. 예컨대 inline 함수가 bar.c에서 정의되어 있다고 가정해 보죠.

foo.c를 컴파일 할 때 보통 bar.c를 보진 않죠. bar.c에 inline function f가 정의되어 있다면, 그걸 foo.c 컴파일 하는 과정에서 보기 어렵습니다. 그게 문제인 것 같구요.

static inline인 경우, f를 bar.c에서는 사용할 수 없고, foo.c에서 사용될 때는 컴파일러가 되도록 inline을 합니다.

extern inline인 경우, f를 bar.c에서 사용할 순 있습니다. 그런데 bar.c에서는 f의 정의를 볼 수는 없기 때문에 그 정의를 가져다가 f를 호출하는 자리에 바꿔 끼울 수는 없습니다. 그렇기 때문에 컴파일러는 extern inline f와 동일한 바디를 갖는 일반 함수 extern f를 생성합니다. 그 f가 bar.c 등 foo.c 밖의 모든 object module에서 사용됩니다. 이렇게 하면 bar.c를 컴파일하면서 f의 타입 이외의 정보는 알 필요가 없거든요.

inline만 있는 경우는 컴파일러가 extern inline f를 갖고 자동으로 extern f를 생성하지 않습니다. 대신 프로그래머가 어디선가 extern f도 제공할 것을 기대합니다.

extern inline은 f 호출한 자리를 inline할 때 사용하는 f의 정의와 bar.c 등 외부에서 f를 부를 때 그 f의 정의가 같습니다. inline은 그 둘이 다를 수 있고, 둘다 모두 프로그래머가 제공해야 합니다.

그래서 inline만 쓸 경우에는 extern f의 정의도 함께 제공해야 합니다.

hellworld의 이미지

undefined function 이 아니라

호출하는 부분에서 undefined reference 에러가 나요

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.