gcc (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0
I'm experimenting with inline and external definitions and here are 2 source files linked together:
foo.c:
#include <stdio.h>
void foo(void){
printf("Test external definition\n");
}
main.c:
#include <stdio.h>
inline void foo(void){
printf("Test\n");
}
int main(void){
foo();
}
Compiling an linking 2 files together Test is printed in console.
N2346::6.7.4/p6 provides that:
It is unspecified whether a call to the function uses the inline
definition or the external definition.
and
If all of the file scope declarations for a function in a translation
unit include the inline function specifier without extern , then the
definition in that translation unit is an inline definition. An inline
definition does not provide an external definition for the function,
and does not forbid an external definition in another translation
unit.
So in the example there are inline definition and external definition. And it's unspecified which one is called.
I ran tests and in my case the inline definition was called. Is there a way to force gcc to call external definition? Maybe there is some flag?
Citing from 6.7.4/10:
A file scope declaration with extern creates an external definition.
For the external definition to be available to choose from (however the compiler chooses) there must actually be an extern function declaration.
From the example:
inline double fahr(double t) { ... }
...
extern double fahr(double); // creates an external definition
Related
I have a function which is initially declared in a header file my.h to have external linkage(no storage class specified)
int myfunc(int);
And this function definition and it's call is present in source file my.c
my.c includes my.h
This all is fine.
But now I wanted to make this function myfunc inline
So I declare a new prototype in my.c
as
__attribute__((always_inline)) static inline int myfunc(int)
and define it so in same function as before,
as expected I keep getting an error saying
static declaration of 'myfunc' follows non-static declaration
I need to keep the non-static,non-inline version of this function for a C reference version of code , and the static inline version for a optimized version of the code.
How can I work around this problem , as I need a static declaration of that function., within this existing source/header files setup I have
One way is I change the name of the static inline function to myfuncinline and work with it!
But is there any way within current setup.
A function defined with static storage-class specifier has internal linkage. You cannot refer to it outside that translation unit.
If you cannot change the declaration of myfunc in the header, then write two
functions in the source file. One called myfuncreal, which does all the work and is defined with static inline:
__attribute__((always_inline)) static inline int myfuncreal(int a)
{
//uses parameter a and returns the result
}
And the other called myreal that wraps around myfuncreal, defined as:
int myfunc(int a)
{
return myfuncreal(a);
}
#ifndef DEBUG
static inline
#endif
int myfunc(int);
Assuming DEBUG is defined in your debug builds but not in your optimized builds. Note that this example is for a declaration in a .c file or a definition in a .h file; for a declaration in a .h and a definition in a .c do
/* foo.h */
#ifdef DEBUG
int myfunc(int);
#endif
/* foo.c */
#ifndef DEBUG
static inline int myfunc(int);
#endif
/* code that uses myfunc() */
#ifndef DEBUG
static inline
#endif
int myfunc(int) {/* definition */}
I read that
A function with internal linkage is only visible to one compilation
unit. (...) A function declared static has internal linkage
For .c files it sorta makes sense, but I was wondering what happens with static functions in headers, which get included by multiple .c files but usually have an include guard.
I was reading this answer about static functions in headers, and the first item mentions that it doesn't create a symbol with external linkage and the second item mentions the function is available purely through the header file. Isn't that contradictory? How can the function be available and at the same time have no external symbol? So I did a little test:
/* 1.h */
#ifndef ONE_H
#define ONE_H
#include <stdio.h>
static void foo() {
printf("foo from 1.h %p\n", foo);
return;
}
void bar();
#endif
/* 1.c */
#include "1.h"
#include <stdio.h>
void bar() {
printf("foo,bar from 1.c %p,%p\n", foo, bar);
foo();
}
/* 2.c */
#include "1.h"
#include <stdio.h>
int main() {
printf("foo,bar from main %p,%p\n", foo, bar);
foo();
bar();
return 0;
}
...
debian#pc:~ gcc 2.c 1.c
debian#pc:~ ./a.out
foo,bar from main 0x400506,0x400574
foo from 1.h 0x400506
foo,bar from 1.c 0x400559,0x400574
foo from 1.h 0x400559
As expected bar is the same across all files, but shouldn't foo be too? Isn't 1.h included only once? Adding inline to foo resulted in the same behavior. I'm kinda lost.
Read here, how a header file basically works. That should clarify about your actual question.
Briefly: A header file is just inserted instead of the corresponding #include directive. So any declarations or definitions are treated by the compiler as if you actually copy/pasted the text into your file.
Anyway, you should be careful with function definitions in a header. This is deemed bad style in general. It blows the code for instance, creating redundant copies of that function. Also Function pointers cannot be compared (you never know ...). It is often better to bundle the functions into a library with just the declarations in a header (non-static then: external linkage). There are good justifications sometimes, however (no rule without exceptions). One of them are inline functions.
-static functions are functions that are only visible to other functions in the same file (more precisely the same translation unit).
Check this article for a detailed explanation on linkage: http://publications.gbdirect.co.uk/c_book/chapter4/linkage.html
I have a weird problem in my Geany project. The project is extremely simple and contains 3 files all in the same directory: main.c, foo.h and foo.c.
Compiler error:
In file included from main.c:1:0:
foo.h:4:12: warning: ‘bar’ used but never defined
static int bar(void);
^
/tmp/cc0zCvOX.o: In function `main':
main.c:(.text+0x12): undefined reference to `bar'
Compilation failed.
collect2: error: ld returned 1 exit status
What is going wrong?
main.c:
#include "foo.h"
int main(int argv, char* argc[])
{
bar();
return 0;
}
foo.h:
#ifndef _FOO_H_
#define _FOO_H_
static int bar(void);
#endif // _FOO_H_
foo.c:
#include "foo.h"
#include <stdio.h>
static int bar(void)
{
printf("Hello World\n");
return 1;
}
If a function is declared as static, the function is in file scope, means the scope of the function is limited to the translation unit only (in this case, the source file). Other functions which are present in the same compilation unit can call the functions, but no functions present outside the compilation unit can see the definition (presence) or call the function.
Related: From C11 standard document, chapter , linkage of identifiers
If the declaration of a file scope identifier for an object or a function contains the storage class specifier static, the identifier has internal linkage.(30)
and, footnote (30),
A function declaration can contain the storage-class specifier static only if it is at file scope;
Solution: Remove the static in the function definition and declaration.
FWIW, there is not much meaning of putting the forward declaration of a static function in a header file. Anyway, the static function can not be called from other source files.
Doing cc -std=c99 example.c on the following simplified example.c file:
inline void a()
{
}
int main()
{
a();
return 0;
}
gets me:
In function `main':
example.c:(.text+0x7): undefined reference to 'a'
collect2: ld returned 1 exit status
As I understand this has to do with the requirement of C99 standard to demand exactly one more definition for each inline non-static function that is used in cases where the body cannot be inlined? If that is so, I am guessing I could do with static inline instead, but I don't want this to bite me later, so what would be the best course of action here? Obviously, I want to stick to C99 and I want to inline some functions. (Yes, I am aware the compiler usually knows what to inline without being told so, but I have my reasons)
Probably you wouldn't have that error when you compile with -O2 or so.
Inline function definitions should go in header files and an extern inline declaration should go in one compilation unit. Do
inline void a(void){
// empty
}
// in just one .c file
#include "the-file.h"
extern inline void a(void);
BTW, declaring a without void is not a prototype.
There's no function prototype, that's all, so the function signature is inferred, and inferred wrong. Add "void a();" to the top of the file, and you're all set.
I'm writing a library in C99, and there are some parts of the library that would benefit significantly from the use of a macro / inline function. Inline functions are a better fit for my library.
However, very specifically I do not want to externally expose these inline functions.
Everything appears to work, but when I link against the library to create an executable I get the error: "undefined reference to `na_impl_gfx__draw'"
I have reproduced the problem to a minimal test case which does exactly what I do:
lib.h:
void somefunc();
lib.c:
#include <stdio.h>
#include "lib.h"
inline void someinline(char *value);
void somefunc() {
someinline("Hi!");
}
inline void someinline(char *value) {
printf("%s\n", value);
}
main.c:
#include "lib.h"
int main(int argc, char *argv[]) {
somefunc();
}
Now we compile:
doug#Wulf:~/test$ gcc -c -std=c99 lib.c
doug#Wulf:~/test$ gcc -c -std=c99 main.c
doug#Wulf:~/test$ gcc -std=c99 lib.o main.o
lib.o: In function `somefunc':
lib.c:(.text+0xe): undefined reference to `someinline'
lib.c:(.text+0x1a): undefined reference to `someinline'
lib.c:(.text+0x26): undefined reference to `someinline'
collect2: ld returned 1 exit status
It would appear that when compiling the library, the inline function is not being substituted into the object code for the function somefunc() in lib.h
Why?
The inline function is not externally visible. I would expect that when the library is compiled, the inline function is inlined into the function, just like the macro is (Nb. using only a macro this code compiles file).
What am I doing wrong? Or is this a restriction of inline functions?
The reason that you can't see the inline function in the same source file is that you haven't made them static.
All you need to do is make the prototype static with:
inline static void someinline(char *value);
and the function definition static with:
inline static void someinline(char *value) {
printf("%s\n", value);
}
[Sorry for kicking in as lately, you should have tagged your question with C and not only C99.]
I think with your question you are completely on the wrong track. Inline functions only make sense when you put them in a ".h" file. The whole concept is about making the function definition visible to all callers.
If you'd do so you should just put the definition (with the inline) in the header and an external declaration (with extern inline) in one compilation unit.
If you just want to have functions put in place in your "lib.o" compilation unit, forget about all that inline or static and let the compiler do that for you. gcc does that if you switch on optimization:
`-finline-small-functions'
Integrate functions into their callers when their body is smaller
than expected function call code (so overall size of program gets
smaller). The compiler heuristically decides which functions
are
simple enough to be worth integrating in this way.
Enabled at level `-O2'.