tags:

views:

377

answers:

3

Hi,

I have gone through some posts related to this topic but was not able to sort out my doubt completely. This might be a very naive question.

I have a header file inline.h and two translation units main.cpp and tran.cpp.

Details of code are as below

inline.h

#ifndef __HEADER__
#include <stdio.h>
extern inline int func1(void)
{ return 5; }

static inline int func2(void)
{ return 6; }

inline int func3(void)
{ return 7; }
#endif

main.c

#define <stdio.h>
#include <inline.h>
int main(int argc, char *argv[])
{
    printf("%d\n",func1());
    printf("%d\n",func2());
    printf("%d\n",func3());
    return 0;
}

tran.cpp

//(note that the functions are not inline here)
#include <stdio.h>
int func1(void)
{ return 500; }

int func2(void)
{ return 600; }

int func3(void)
{ return 700; }

The above code compiles in g++, but does not compile in gcc (even if you make changes related to gcc like changing the code to .c, not using any C++ header files, etc.). The error displayed is "duplicate definition of inline function - func3".

Can you clarify why this difference is present across compilers?

Also, when you run the program (g++ compiled) by creating two separate compilation units (main.o and tran.o) and create an executable a.out, the output obtained is:

500
6
700

Why does the compiler pick up the definition of the function which is not inline. Actually, since #include is used to "add" the inline definition I had expected 5,6,7 as the output. My understanding was during compilation since the inline definition is found, the function call would be "replaced" by inline function definition.

Can you please tell me in detailed steps the process of compilation and linking which would lead us to 500,6,700 output. I can only understand the output 6.

+1  A: 

Maybe you should post the actual code. The snippets you show don't compile:

  • inline.h has extern inline int func1(void) That doesn't make any sense.
  • main.h has #define <stdio.h> I think you meant include instead.

Once I fixed those and compiled with gcc, it compiled fine and I got the following output

5
6
7

When I compile with g++, I get this output:

5
6
700

That happens because func3() is not static in inline.h

JayM
`extern inline` is used by some compilers to say "inline this if you see a use and can inline, but if you see a use where it cannot be inlined assume that another compilation unit will provide a non-inline version of this function". Inability to inline could be because the function's address was assigned to a variable or passed to another function. I believe that gcc header files use `extern inline` quite often.
nategoose
A: 

I am really sorry for a non-compiled code. Please find the actual (Compiled) code.

Code Description

  1. main.c file

#include <stdio.h>
#include "inline.h"
int main( int argc, char* argv[])
{

printf("Calling Plain inline function - Direct Call call\n");
printf("%d\n",iitest());

printf("Calling static  inline function - Direct Call call\n");
printf("%d\n",sitest());

printf("Calling extern inline function - Direct Call call\n");
printf("%d\n",eitest());

return 0;

}

  1. inline.h file
    #ifndef __INLINE_H
    #define __INLINE_H

    static inline int sitest(void) { return 5; }

    extern inline int eitest(void) { return 6; }

    inline int iitest(void) { return 7; }

    #endif

  2. another translation unit (Say inline2.c file)

#include <stdio.h>

int sitest(void) { return 500; }

int eitest(void) { return 600; }

int iitest(void) { return 700; }

Compiler and compilation details

a) Using built-in specs. Target: x86_64-linux-gnu Configured with: ../src/configure -v --with-pkgversion='Ubuntu 4.4.1-4ubuntu9' --with-bugurl=file:///usr/share/doc/gcc-4.4/README.Bugs --enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr --enable-shared --enable-multiarch --enable-linker-build-id --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.4 --program-suffix=-4.4 --enable-nls --enable-clocale=gnu --enable-libstdcxx-debug --enable-objc-gc --disable-werror --with-arch-32=i486 --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu Thread model: posix gcc version 4.4.1 (Ubuntu 4.4.1-4ubuntu9)

b) g++ -c main.c
g++ -c inline2.c
g++ -o testinline inline2.o main.o

Output

Calling Plain inline function - Direct Call call
700
Calling static inline function - Direct Call call
5
Calling extern inline function - Direct Call call
600

Note:

Changing g++ to gcc in compilation, below error is seen
main.o: In function `iitest' :
main.c:(.text+0xb): multiple definition of `iitest'
inline2.o:inline2.c:(.text+0x16): first defined here
collect2: ld returned 1 exit status

gcc version -
Using built-in specs. Target: x86_64-linux-gnu Configured with: ../src/configure -v --with-pkgversion='Ubuntu 4.4.1-4ubuntu9' --with-bugurl=file:///usr/share/doc/gcc-4.4/README.Bugs --enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr --enable-shared --enable-multiarch --enable-linker-build-id --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.4 --program-suffix=-4.4 --enable-nls --enable-clocale=gnu --enable-libstdcxx-debug --enable-objc-gc --disable-werror --with-arch-32=i486 --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu Thread model: posix gcc version 4.4.1 (Ubuntu 4.4.1-4ubuntu9)

Again Thanks in advance for suggestion.

Question

a. Just wanted to know why the non-inline function from the second TU is picked up by the compiler when the function call is made (Exact steps/rules of binding a function when both inline/non-inline definition are found).

b. Why the compilation fails with gcc compiler? what are the differences between gcc and its cousin g++ [:)]

k71993
You should have edited your question rather than post this as an answer.
nategoose
A: 

The compile error you see is actually a linker error.

gcc and g++ are treating static inline a little differently. inline was first part of C++ and then made into an extension to many C compilers, before being added to standard C. The standard semantics could be different, but it could just be the implementations that are different.

It could also have something to do with some crazy stuff that happens with C++ code that gets rid of duplicate template stuff catching other duplicate stuff as well.

nategoose