C: Pointer to inline function - c

I have a static inline function defined in an H file, and at one point in a C file, I'm assigning a pointer to the function, something like this:
foo.h:
static inline void frobnicate(void) {
// frobs something.
}
foo.c
#include "foo.h"
void execute(void (*func)(void) ) {
func();
}
void blahBlahBlah(void) {
execute(frobnicate);
}
bar.c
#include "foo.h"
// ...
frobnicate();
So I think what will happen here is that the compiler will inline the call to frobnicate from bar.c, but in foo.c, it will actually have to create a function to implement frobnicate, so that it can have a working pointer to it.
Can anyone confirm if my understanding is accurate, and correct me otherwise?

inline is one of the misnomers of the C standard. Its main meaning is to be able to put the definition of a function in a header file without having to deal with "multiple definition" problems at link time.
The official way in C99 and C11 to do what you want to achieve is to have the inline definition in the header file, without the static. Since you also need the symbol to be emitted you need to tell the compiler in which compilation unit this should be. Such an instantiation can be done by have a declaration in that .c file where you omit the inline keyword.
Most naturally you could use the .c file where you actually need the symbol.

Yes, you are right. When you take the pointer to the function the compiler must create an "stand alone" version where the code can be called as a normal function.
The benefit of inlining a function is that the calling code need not to be created and any other optimization can be aplied to integrate both the caller function and the inlined function. But when you need to do a regular call to the function(as when you take the address to call it latter), those optimizations are not possible anymore.

Related

Should I define functions in .h file or just declare them?

I'm new to C and I came across this statement:
"Functions need to be declared in .h files and not defined with exception of inline functions".
My question is then, where are standard functions defined?
"Functions need to be declared in .h files and not defined with exception of inline functions".
You declare the existence of a function in the header. For all dependents to see.
You implement (define) the function in the source file. Dependents cannot see this.
The header file is the API or your C file for use elsewhere in your application, hiding the implementation.
The exception for inline functions has to do with the fact that when compiling the dependent, the compiler must know what to put instead of the function call.
Functions for (private) use only inside your source file do not need to be declared in the header file. Why tell other code about it?
My question is then where are standard functions defined?
In the compiled library. You only know that they exist, not where they exist. The implementation is hidden from you. The linker connects the dots.
Yes functions are declared in .h file and they are defined in .c file
"Functions need to be declared in .h files and not defined with exception of inline functions"
Unknown Source
Unfortunately, this quote is ambiguous and not entirely correct as well.
Functions do not necessary need to be declared in .h files. You can declare a function in .c files as well, or even omit the declaration entirely (dependent upon your coding style and the place of the function definition).
Note for the latter, that the compiler reads a file from top to bottom.
For example, This is the content of the source file foo.c:
void foo (void)
{
// absolute foo / translated: It really does not make anything useful.
// this function is only to illustrate the omission of the prototype.
}
int main (void)
{
foo();
}
To call foo() we need no declaration of foo() at all because the definition is before its use in the source code (compiler reads from top to bottom).
Would it be behind, we would need a declaration to tell the compiler what foo() is, f.e.:
void foo (void); // foo() needs to be declared. Else the compiler does not know
// what foo is when foo is called in main.
int main (void)
{
foo();
}
void foo (void)
{
// absolute foo.
}
It is just a common use to place the declaration/ prototype of a function in a separate header, but you actually do not need to do so. This is the header version:
foo.c:
#include "foo.h" // We need to include the header to gain the prototype.
// Note that `foo.h` needs to be in the same directory
// as `foo.c` in this case. Else you need to specify the
// full path to foo.h .
int main (void)
{
foo();
}
void foo (void)
{
// absolute foo.
}
foo.h:
void foo (void);
What the quote really means is:
A function definitely should not be defined in an .h file (as these are headers, not source files), with the only exception of inline functions, which indeed can be defined in .h files.
"My question is then, where are standard functions defined?"
That is a completely different question and implementation-specific. The functions are stored in an either fully or semi-compiled form. I can not answer it here without the focus to any specific implementation (OS, compiler).

Does an inline funcion in the header must be inserted to everywhere it is called from?

I always though that the compiler can choose between inserting the function as is or to treat it as a regular function.
However I don't think it is possible if the inline function is defined in the header file (and can be included from multiple source files).
Is this correct?
Thanks
Yes, the compiler is completely free to chose if he really inlines an inline function. Actually he is free to inline any function, for which he has seen a definition.
inline as a keyword was introduced to avoid the "multiple symbol definition" problem. As such, it only makes sense if you have the definition in a header file.
The usual scheme is to have a definition like
inline void toto(void) {
...
}
in a header file that is included by several TU. Then in exactly one TU you have a declaration without inline
void toto(void);
which ensures that the symbol is exported by this TU.
In ISO C99 and ISO C11, having in the header file:
inline void f(void) { ..... }
means that the compiler can indeed choose between inlining the function, or treating it as a regular function.
However, when treating as a regular function, the compiler will behave similarly to if you had written void f(void);, i.e. it will expect to link to a body of f elsewhere.
So you need to put in exactly one of your translation units the line:
extern inline void f(void);
which causes the compiler to emit the body in that unit.
However, in GNU C, using inline void f(void) { ... } leads to undefined behaviour. The compiler can still choose, but when it chooses to treat as a regular function, it behaves as if you had written void f(void) { ... }, i.e. it emits the function body in every translation unit that uses it.
Some people write their functions in the header as static inline void f(void) { .... }, which works in both ISO C and GNU C, but possibly makes it harder for the linker to combine all of the copies into one.
See this thread for more detail
Assuming that an inline function is defined in a header like:
inline void f(void) {
...
}
...I can see two questions in your message, indeed:
Do you have to include that header with function definition in every
translation unit (TU) in which you are going to use this function?
Is the compiler free to inline the function in some TUs, while not
inlining it in other TUs, within the same project?
Ad.1: Short answer: Yes.
Long answer:
For compilation, definition (not only declaration!) of an inline function must be visible in every TU, where you are going to call it. Including the header in every TU is the best solution here.
By omitting the function’s storage class specifier in the header (as in the above code snippet, which is OK here, see below for short discussion on using extern or static), you go with the default, which means for inline functions: inline keyword is active in each TU in which you include this header. The function retains default external linkage (!), so it is also accessible from other TUs (i.e. in TUs not including this header), but the keyword inline is not active in the TUs that do not include functions’ inlined definition.
Now the linker must put a version of the function in some of the object files, so the function can be linked from the object files generated from TUs which do not include this functions’ ‘inline’ definition (or to the TUs where compiler decided not to inline despite the inline keyword).
You indicate that single TU by re-declaring the function as non-inlined, by adding after the included header file:
void f(void);
If you add static before your inline function definition in header, then each TU will generate its own copy and your executable code will probably take more space (subject to the zillion factors influencing code size with inlining). But you do not need to re-declare the function in any TU as non-inlined.
If you add extern to your inline function definition in header, then you will get ‘undefined reference’ linker error as none of TUs will generate executable code for it, despite possessing function’s definition (=knowing its body). To avoid it, at least one TU must additionally contain non-static re-declaration of this function:
inline void f(void);
(Note that GCC implements three different inlining semantics in C programs (GNU C90, gnu_inline, and one used e.g. with -std=c99), but to my knowledge none of them conforms to the above.)
Ad2: Yes. Even within a single TU the compiler is free to inline only a subset of calls to the inline function, or inline all calls, or none. Being honest, the same applies to functions defined without the inline keyword, because most compilers will try to ‘inline’, as part of their optimizations, even when the keyword is not used. After all, the keyword is just a hint to the compiler, as others have already highlighted in their comments/responses.

If function declaration is not in header file, is static keyword necessary?

If a function declaration isn't in a header file (.h), but is instead only in a source file (.c), why would you need to use the static keyword? Surely, if you only declare it in a .c file, it isn't seen by other files, as you're not supposed to #include .c files, right?
I have already read quite a few questions and answers about this (eg. here and here), but can't quite get my head around it.
What static does is make it impossible to declare and call a function in other modules, whether through a header file or not.
Recall that header file inclusion in C is just textual substitution:
// bar.c
#include "header.h"
int bar()
{
return foo() + foo();
}
// header.h
int foo(void);
gets preprocessed to become
int foo(void);
int bar()
{
return foo() + foo();
}
In fact, you can do away with header.h and just write bar.c this way in the first place. Similarly, the definition for foo does not need to include the header in either case; including it just adds a check that the definition and declaration for foo are consistent.
But if you were to change the implementation of foo to
static int foo()
{
// whatever
return 42;
}
then the declaration of foo would cease to work, in modules and in header files (since header files just get substituted into modules). Or actually, the declaration still "works", but it stops referring to your foo function and the linker will complain about that when you try to call foo.
The main reason to use static is to prevent linker clashes: even if foo and bar were in the same module and nothing outside the module called foo, if it weren't static, it would still clash with any other non-static function called foo. The second reason is optimization: when a function is static, the compiler knows exactly which parts of the program call it and with what arguments, so it can perform constant-folding, dead code elimination and/or inlining.
The static keyword reduces the visibility of a function to the file scope. That means that you can't locally declare the function in other units and use it since the linker does not add it to the global symbol table. This also means that you can use the name in other units too (you may have a static void testOutput(); in every file, that is not possible if the static is omitted.)
As a rule of thumb you should keep the visibility of symbols as limited es possible. So if you do not need the routine outside (and it is not part of some interface) then keep it static.
It allows you to have functions with identical names in different source files, since the compiler adds an implicit prefix to the name of every static function (based on the name of the file in which the function is located), thus preventing multiple-definition linkage errors.
It helps whoever maintains the code to know that the function is not exposed as part of the interface, and is used only internally within the file (a non-static function can be used in other source files even if it's not declared in any header file, using the extern keyword).

C inline functions and "undefined external" error

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.

gcc warning: function used but not defined

I am getting the warning: function used but not defined. I have static
__inline__ in header file say a.h. The header file is included in a.c. I would like put all those inline function which are in header files into the .c files. Following code gives the idea of my problem.
Orginal code:
a.h:
static __inline__ function1(){
function definition;
}
I changed:
a.h:
static function1();
a.c:
#include "a.h"
static function1(){
function definition;
}
On doing above I got the warning:
warning: function function1 is used but not defined.
Could you please let me know why i am getting such warning? I would like to transfer all the __inline__ function into the .c so that I won't get the warning:
warning: function1 is could not be inlined, code size may grow.
Thanks in advance
You've declared the function to be static. This means that it is only visible within the current compilation unit. In other words: the implementation is only visible inside the a.c file. You need to remove the static keyword both in the a.h and a.c so that other .c files can see the function. You should specify a return value, e.g. void function1(); because it implicitly is int if you didn't specify one.
Functions declared static within a .c file are only visible/usable within that file only. If they are not used in it, then they are effectively dead code and the compiler warns you about this fact. In GCC you can use the unused function attribute to suppress this warning:
static int __attribute__((unused)) function1() {
...
}
EDIT:
In general you should usually follow the following guidelines regarding inline functions:
If they are used in multiple C files, declare them static and have their definition in an included header file. That allows all .c files that include that header to have their own private definition of the function, which allows the compiler to inline it. Lone static function prototypes make little to no sense in a header file that will be used by multiple source files, since their actual definitions will be missing.
If they are not intended to be reused, have their definition (and, if necessary, their prototype) in the .c file where they are supposed to be used.
If GCC complains about being unable to inline a function, due to the function size:
Ask yourself if you really need that function to be inlined - from my experience, the compiler usually knows best.
If you really, really want that function inlined, the always_inline function attribute may be of use. You may also have to provide a non-default -finline-limit=n option to GCC to increase the allowed size for inline functions.
See also this for additional information on inline functions and some possible pitfalls regarding their use.
EDIT 2:
If you have a static inline function defined in a shared header file and want to turn it into a normal, for lack of a better word, function you should:
Select a .c file where the presence of that function make sense (i.e. put it with other related functions).
Remove the static and inline keywords from its definition and move the definition from the header into that file.
Remove the static and inline keywords from its prototype and put it into the header file.
Congratulations, you now have a normal publicly-available function.
Disclaimer: you just made a function that was private to a number of files, public to all of your program. If there is another public symbol - variable or function - with the same name, you may get errors while linking or even strange behaviour at runtime. You've been warned...
Declare the function normally in the header file
a.h
#ifndef A_H_INCLUDED
#define A_H_INCLUDED
void function1(void);
#endif
Define the function in a single code file with no static
a.c
#include "a.h"
void function1(void) {
/* function definition */
}
and call the function from other files, after including the header
b.c
#include "a.h"
void quux(void) {
function1(); /* call regular function */
}
The way you had before (static and implementation in header file) worked because each code file that included that header got its own version of the function; different to every other function of the same name in every other file (but doing exactly the same).

Resources