The C language allows source files to be read in a single pass without looking ahead; at any point the compiler only has to consider declarations, prototypes, macro definitions etc. that have appeared before its current position in the file.
Does this mean that for a function call to be inlined, a compiler might require the function to be defined before the call? For example:
int foo(void);
int bar(void) { return foo(); }
inline int foo(void) { return 42; }
Is the call to foo more likely to be inlined if the inline definition is moved in front of the definition of bar?
Should I arrange inline definitions in my code so that they appear before the calls that should best be inlined? Or can I just assume that any optimizing compiler that is advanced enough to do inlining at all will be able to find the definition even if it appears after the call (which seems to be the case with gcc)?
EDIT: I noticed that in the Pelles C with the /Ob1 option indeed requires the definition to visible before a call can be inlined. The Compiler also offers an /Ob2 option which removes this limitation (and also allows the compiler to inline functions without an inline specifier, similar to what gcc does), but the documentation states that using this second option may require much more memory.
It shouldn't make any difference in practice. Because, its compiler's choice to inline a function or not even if it's explicitly told to inline. Compiler may also inline a function even if it's defined using inline keyword.
First, I ran your code with with gcc 4.6.3 without any optimizations:
$ gcc -fdump-ipa-inline test.c
From the generated assembly both foo and bar are not inlined even though foo is inlined.
When I changed put the definition of inline foo at the top, the compiler still didn't inline both.
Next I did the same with -O3:
$ gcc -fdump-ipa-inline -O3 test.c
Now both the functions are inlined. Even though only one has the inline declaration.
Basically the compiler can inline a function as it sees fit.
Related
Why doesn't the following program compile with clang?
#include <stdio.h>
inline int f() {
return 42;
}
int main() {
printf("%d\n", f());
}
I get the following:
$ clang -o inline inline.c
Undefined symbols for architecture arm64:
"_f", referenced from:
_main in inline-975155.o
ld: symbol(s) not found for architecture arm64
clang-12: error: linker command failed with exit code 1 (use -v to see invocation)
But I can compile it with clang++ just fine. Is there some nuance between inline in C vs C++?
In C99 you need to provide an alternate (non-inline) definition of the function for when the compiler can't inline. See https://clang.llvm.org/compatibility.html#inline
One of the solutions may work for you, is to make the definition static:
#include <stdio.h>
static inline int f() {
return 42;
}
int main() {
printf("%d\n", f());
}
will work as you expect.
Here are all the options listed in the on the linked clang page:
Change add to a static inline function. This is usually the right solution if only one translation unit needs to use the function. static inline functions are always resolved within the translation unit, so you won't have to add a non-inline definition of the function elsewhere in your program.
Remove the inline keyword from this definition of f. The inline keyword is not required for a function to be inlined, nor does it guarantee that it will be. Some compilers ignore it completely. Clang treats it as a mild suggestion from the programmer.
Provide an external (non-inline) definition of f somewhere else in your program. The two definitions must be equivalent!
Compile in the GNU C89 dialect by adding -std=gnu89 to the set of Clang options. This option is only recommended if the program source cannot be changed or if the program also relies on additional C89-specific behavior that cannot be changed.
In 6.7.4 7, the C 2018 standard says an inline definition does not provide an external definition:
… An inline definition does not provide an external definition for the function…
and that a compiler may use an inline definition or an external definition:
… It is unspecified whether a call to the function uses the inline definition or the external definition.
Thus, a compiler may compile a call to f as a call to the inline definition, which will not result in a link error, or as a call to an external definition, which will result in a link error if you have not provided an external definition. The compiler’s choice may be affected by optimization switches and other settings.
The C++ standard does not have this wording (but I will leave it to others to provide additional interpretation of the C++ standard).
Very simple: Inlining does not work if you do not enable optimizations.
https://godbolt.org/z/KrWq4PGhd
To sort this problem out you need to instruct the compiler to emit not inline version as well:
extern inline int f() {
return 42;
}
Then it will work in both cases (will be inlined or not)
https://godbolt.org/z/dh3G18PqK
CLANG works exactly the same way:
https://godbolt.org/z/ssMnzf5MG
https://godbolt.org/z/ssMnzf5MG
I am confused about inline in C99.
Here is what I want:
I want my function get inlined everywhere, not just limited in one translation unit (or one compilation unit, a .c file).
I want the address of the function consistent. If I save the address of the function in a function pointer, I want the function callable from the pointer, and I don't want duplication of the same function in different translation units (basically, I mean no static inline).
C++ inline does exactly this.
But (and please correct me if I am wrong) in C99 there is no way to get this behavior.
I could have use static inline, but it leads to duplication (the address of the same function in different translation unit is not the same). I don't want this duplication.
So, here are my questions:
What is idea behind inline in C99?
What benefits does this design give over C++'s approach?
References:
Here's a link that speaks highly of C99 inline, but I don't understand why. Is this “only in exactly one compilation unit” restriction really that nice?http://gustedt.wordpress.com/2010/11/29/myth-and-reality-about-inline-in-c99/
Here's the Rationale for C99 inline. I've read it, but I don't understand it.Is "inline" without "static" or "extern" ever useful in C99?
A nice post, provides strategies for using inline functions.http://www.greenend.org.uk/rjk/tech/inline.html
Answers Summary
How to get C++ inline behavior in C99 (Yes we can)
head.h
#ifndef __HEAD_H__
#define __HEAD_H__
inline int my_max(int x, int y) {
return (x>y) ? (x) : (y);
}
void call_and_print_addr();
#endif
src.c
#include "head.h"
#include <stdio.h>
// This is necessary! And it should occurs and only occurs in one [.c] file
extern inline int my_max(int x, int y);
void call_and_print_addr() {
printf("%d %u\n", my_max(10, 100), (unsigned int)my_max);
}
main.c
#include <stdio.h>
#include "head.h"
int main() {
printf("%d %u\n", my_max(10, 100), (unsigned int)my_max);
call_and_print_addr();
return 0;
}
Compile it with: gcc -O3 main.c src.c -std=c99
Check the assembly with: gcc -O3 -S main.c src.c -std=c99, You'll find that my_max is inlined in both call_and_print_addr() and main().
Actually, this is exactly the same instructions given by ref 1 and ref 3. And what's wrong with me?
I used a too old version of GCC (3.4.5) to experiment, it give me “multiple definition of my_max” error message, and this is the real reason why I am so confused. Shame.
Difference between C99 and C++ inline
Actually you can compile the example above by g++: g++ main.c src.c
extern inline int my_max(int x, int y);
is redundant in C++, but necessary in C99.
So what does it do in C99?
Again, use gcc -O3 -S main.c src.c -std=c99, you'll find something like this in src.s:
_my_max:
movl 4(%esp), %eax
movl 8(%esp), %edx
cmpl %eax, %edx
cmovge %edx, %eax
ret
.section .rdata,"dr"
If you cut extern inline int my_max(int x, int y); and paste it into main.c, you'll find these assembly code in main.s.
So, by extern inline, you tell the compiler where the true function my_max(), which you can call it by its address, will be defined and compiled.
Now look back in C++, we can't specify it. We will never know where my_max() will be, and this is the “vague linkage” by #Potatoswatter.
As is said by #Adriano, most of the time, we don't care about this detail, but C99 really removes the ambiguity.
To get C++-like behavior, you need to give each TU with potentially-inlined calls an inline definition, and give one TU an externally-visible definition. This is exactly what is illustrated by Example 1 in the relevant section (Function specifiers) of the C standard. (In that example, external visibility is retroactively applied to an inline definition by declaring the function extern afterward: this declaration could be done in the .c file after the definition in the .h file, which turns usual usage on its head.)
If inlining could be accomplished literally everywhere, you wouldn't need the extern function. Non-inlined calls are used, however, in contexts such as recursion and referencing the function address. You may get "always inline" semantics, in a sense, by omitting the extern parts, however this can arbitrarily fail for any simple function call because the standard does not demand that a call be inlined just because there is no alternative. (This is the subject of the linked question.)
C++ handles this with the implementation concept of "vague linkage"; this isn't specified in the standard but it is very real, and tricky, inside the compiler. C compilers are supposed to be easier to write than C++; I believe this accounts for the difference between the languages.
I want my function get inlined everywhere, not just limited in one translation unit(or one compile unit, a [.c] file).
With inline you politely ask your compiler to inline your function (if it has time and mood). It's unrelated to one compilation unit, at best it may even get inlined in every single call site and it won't have a body anywhere (and its code will be duplicated everywhere). It's purpose of inlining, speed in favor of size.
I want the address of the function consistent. If I save the address of the function in a function pointer, I want the function callable from the pointer, and I don't want duplication of the same function in different translation unit. (Basically, I mean no 'static inline')
Again you can't. If function is inlined then there is not any function pointer to it. Of course compiler will need a compilation unit where function will stay (because, well yes, you may need a function pointer or sometimes it may decide to do not inline that function in a specific call site).
From your description it seems that static inline is good. IMO it's not, a function body (when used, see above paragraph) in each compilation unit will lead to code duplication (and problem in comparison of function pointers because each compilation unit will have its own version of your function). It's here that C99 did something pretty good: you declare exactly one place to put function body (when and if required). Compiler won't do it for you (if you ever care about it) and there is nothing left to implementor.
What is idea behind inline in C99?
Pick a good thing (inline functions) but remove ambiguity (each C++ compiler did his own job about where function body has to stay).
What benefits does this design give over C++'s approach?
Honestly I can't see such big problem (even article you linked is pretty vague about this benefit). In a modern compiler you won't see any issue and you will never care about that. Why it's good what C did? IMO because it removed an ambiguity even if - frankly speaking - I'd prefer my compiler does that for me when I don't care about it (99.999%, I suppose).
That said, but I may be wrong, C and C++ have different targets. If you're using C (not C++ without classes and few C++ features) then probably you want to address this kind of details because they matters in your context so C and C++ had to diverge about that. There is not a better design: just different decision for a different audience.
This part of the gcc manual is pretty obscure and i can't understand the usage of the forceinline attribute after repeated attempts.
I'm defining an object and certain functions to manipulate that object. Few of those functions can use atomic instructions and i want the compiler to inline those functions. However i do not want to write those functions in the header file and declare them with "static inline" like in the linux kernel.
Is there a way to force gcc to inline functions from another translation unit ?
you can use the always_inline attribute, for example:
void foo () __attribute__((always_inline));
From the docs
always_inline
Generally, functions are not inlined unless optimization is specified. For functions declared inline, this attribute inlines the
function even if no optimization level was specified.
Note1: There's no need to use inline if you use the always_inline attribute
Note2: If the function could not be inlined you will get a warning, if for example the definition is not available when compiling, however, at a higher optimization gcc can still inline it into the caller, there's a specific switch for that too:
-funit-at-a-time
From the docs:
Optimization levels -O2 and above, in particular, enable
unit-at-a-time mode, which allows the compiler to consider information
gained from later functions in the file when compiling a function.
Compiling multiple files at once to a single output file in
unit-at-a-time mode allows the compiler to use information gained from
all of the files when compiling each of them.
Note3:
It is not necessary to have an explicit prototype so you can use the attribute on the function defintion:
__attribute__((always_inline)) void foo() {
//some code
}
Also see this discussion, it answers some of your questions.
I'm trying to replace some macro subroutines with inline functions, so the compiler can optimize them, so the debugger can step into them, etc. If I define them as normal functions it works:
void do_something(void)
{
blah;
}
void main(void)
{
do_something();
}
but if I define them as inline:
inline void do_something(void)
{
blah;
}
void main(void)
{
do_something();
}
it says "Error: Undefined external". What does that mean? Taking a stab in the dark, I tried
static inline void do_something(void)
{
blah;
}
void main(void)
{
do_something();
}
and no more errors. The function definition and call to the function are in the same .c file.
Can someone explain why one works and the other doesn't?
(Second related question: Where do I put inline functions if I want to use them in more than one .c file?)
First, the compiler does not always inline functions marked as inline; eg if you turn all optimizations off it will probably not inline them.
When you define an inline function
inline void do_something(void)
{
blah
}
and use that function, even in the same file, the call to that function is resolved by the linker not the compiler, because it is implicitely "extern". But this definition alone does not provide an external definition of the function.
If you include a declaration without inline
void do_something(void);
in a C file which can see the inline definition, the compiler will provide an external definition of the function, and the error should go away.
The reason static inline works is that it makes the function visible only within that compilatioin unit, and so allows the compiler to resolve the call to the function (and optimize it) and emit the code for the function within that compilation unit. The linker then doesn't have to resolve it, so there is no need for an external definition.
The best place to put inline function is in a header file, and declare them static inline. This removes any need for an external definition, so it resolves the linker problem. However, this causes the compiler to emit the code for the function in every compilation unit that uses it, so could result in code bloat. But since the function is inline, it is probably small anyway, so this usually isn't a problem.
The other option is to define it as extern inline in the header, and in one C file provide and extern declaration without the inline modifier.
The gcc manual explains it thus:
By declaring a function inline, you can direct GCC to make calls to
that function faster. One way GCC can achieve this is to integrate
that function's code into the code for its callers. This makes
execution faster by eliminating the function-call overhead; in
addition, if any of the actual argument values are constant, their
known values may permit simplifications at compile time so that not
all of the inline function's code needs to be included. The effect on
code size is less predictable; object code may be larger or smaller
with function inlining, depending on the particular case. You can
also direct GCC to try to integrate all "simple enough" functions into
their callers with the option -finline-functions.
GCC implements three different semantics of declaring a function
inline. One is available with -std=gnu89 or -fgnu89-inline or
when gnu_inline attribute is present on all inline declarations,
another when -std=c99, -std=c1x, -std=gnu99 or -std=gnu1x
(without -fgnu89-inline), and the third is used when compiling C++.
To declare a function inline, use the inline keyword in its
declaration, like this:
static inline int
inc (int *a)
{
return (*a)++;
}
If you are writing a header file to be included in ISO C90 programs,
write __inline__ instead of inline.
The three types of inlining behave similarly in two important cases:
when the inline keyword is used on a static function, like the
example above, and when a function is first declared without using the
inline keyword and then is defined with inline, like this:
extern int inc (int *a);
inline int
inc (int *a)
{
return (*a)++;
}
In both of these common cases, the program behaves the same as if you
had not used the inline keyword, except for its speed.
When a function is both inline and static, if all calls to the
function are integrated into the caller, and the function's address is
never used, then the function's own assembler code is never
referenced. In this case, GCC does not actually output assembler code
for the function, unless you specify the option
-fkeep-inline-functions. Some calls cannot be integrated for various
reasons (in particular, calls that precede the function's definition
cannot be integrated, and neither can recursive calls within the
definition). If there is a nonintegrated call, then the function is
compiled to assembler code as usual. The function must also be
compiled as usual if the program refers to its address, because that
can't be inlined.
Note that certain usages in a function definition can make it
unsuitable for inline substitution. Among these usages are: use of
varargs, use of alloca, use of variable sized data types , use of computed goto,
use of nonlocal goto, and nested functions.
Using -Winline will warn when a function marked inline could not
be substituted, and will give the reason for the failure.
As required by ISO C++, GCC considers member functions defined within
the body of a class to be marked inline even if they are not
explicitly declared with the inline keyword. You can override this
with -fno-default-inline.
GCC does not inline any functions when not optimizing unless you
specify the always_inline attribute for the function, like this:
/* Prototype. */
inline void foo (const char) __attribute__((always_inline));
The remainder of this section is specific to GNU C90 inlining.
When an inline function is not static, then the compiler must
assume that there may be calls from other source files; since a global
symbol can be defined only once in any program, the function must not
be defined in the other source files, so the calls therein cannot be
integrated. Therefore, a non-static inline function is always
compiled on its own in the usual fashion.
If you specify both inline and extern in the function definition,
then the definition is used only for inlining. In no case is the
function compiled on its own, not even if you refer to its address
explicitly. Such an address becomes an external reference, as if you
had only declared the function, and had not defined it.
This combination of inline and extern has almost the effect of a
macro. The way to use it is to put a function definition in a header
file with these keywords, and put another copy of the definition
(lacking inline and extern) in a library file. The definition in
the header file will cause most calls to the function to be inlined.
If any uses of the function remain, they will refer to the single copy
in the library.
For inline functions to work with C99 (they only came there into the language) you'd have to give the definition in a header file
inline void do_something(void)
{
blah
}
and in one compilation unit (aka .c) you place some sort of "instantiation"
void do_something(void);
without the inline.
You have to put them in a header file if you want to use them from multiple files.
And for the linker error: the default declaration of a function implies that it's "extern", but since it's inlined, the linker can find the compiler-generated symbol stub, hence the error.
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.
This answer is divided into the following sections:
How to reproduce the duplicate definition of inline function - func3 problem and why.
Why defintion of func3 is a duplicate instead of func1.
Why it compiles using g++
How to produce the duplicate definition of inline function - func3 problem
The problem can be successfully reproduced by
Rename tran.cpp to tran.c
Compile with gcc -o main main.c tran.c
#K71993 is actually compiling using the old gnu89 inline semantics, which is different from C99. The reason for renaming tran.cpp to tran.c is to tell the gcc driver to treat it as C source instead of C++ source.
Why definition of func3 is a duplicate instead of func1.
GNU 89 inline semantics
The following text is quoted from GCC Document: An Inline Function is As Fast As a Macro explains why func3 is a duplicate definition instead of func1, since func3 (instead of func1) is an externally visible symbol (in GNU89 inline semantics)
When an inline function is not static, then the compiler must assume that there may be calls from other source files; since a global symbol can be defined only once in any program, the function must not be defined in the other source files, so the calls therein cannot be integrated. Therefore, a non-static inline function is always compiled on its own in the usual fashion.
If you specify both inline and extern in the function definition, then the definition is used only for inlining. In no case is the function compiled on its own, not even if you refer to its address explicitly. Such an address becomes an external reference, as if you had only declared the function, and had not defined it.
C99 inline semantics
If compiled with C99 standard, i.e., gcc -o main main.c tran.c -std=c99, the linker will complain that definition of func1 is a duplicate due to the reason that extern inline in C99 is a external definition as mentioned in other posts and comments.
Please also refer to this execellent answer about semantic differents between GNU89 inline and C99 inline.
Why it compiles using g++.
When compiled with g++, the source program are considered as C++ source. Since func1, func2 and func3 are defined in multiple translation units and their definitions are different, the One Defintion Rule of C++ is violated. Since the compiler is not required to generate dignostic message when definitions spans multiple translation units, the behavior is undefined.
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
The compiling error is because there is a duplicate definition of func1();
Because func1() is defined using extern inline, it will produce a external definition.
However, there is also an external definition in tran.c, which cause multiple definition error.
However, func2() and func3() do not produce an external definition, hence no redefinition error.
You might want to look at here http://www.greenend.org.uk/rjk/2003/03/inline.html.
Also, take a note that c++ and c treats inline functions differently, and even in c, different standards (c89 vs. c99) treats inline functions differently.
Your code is invalid from the C++ point of view, since it blatantly violates the One Definition Rule. The only reason you managed to compile it by C++ compiler is the loose error checking in your C++ compiler (it happens to be one of those parts of ODR where "no diagnostic is required").
Your code is not valid C, because it provides duplicate external definition of function func1. Note that it is func1, not func3 that is problematic from the C point of view. There's nothing formally wrong with your func3. Your func2 is also OK, as long as the two definitions never "meet" each other in the same translation unit.
One possible reason you might be getting a different diagnostic report from your compiler is that your C compiler might be supporting inline functions in some non-standard compiler-specific way (either a pre-C99 compiler or a modern compiler run in non-standard "legacy" mode).
Frankly, I find it hard to believe you are getting an error report about func3 from any compiler, assuming the code you posted accurately represents what you are trying to compile. Most likely what you posted is not the real code.
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.
basically Inline is a late entry to GCC ( I mean c compiler).
"[ . . . ] An inline definition does not provide an external definition for the function, and does not forbid an external definition in another translation unit. An inline definition provides an alternative to an external definition, which a translator may use to implement any call to the function in the same translation unit. It is unspecified whether a call to the function uses the inline definition or the external definition."
— ISO 9899:1999(E), the C99 standard, section 6.7.4