May be my question is a little bit silly, but I can't get this code to work correctly. I have read similar question with answers, but there were a little bit different situation.
So, the question is: "Is it possible to get static variable value in inline functions?"
I code the program for microcontroller with small amount of memory and low speed. For some reason I need to make some functions inline (to save memory and time of execution).
This is the problem description:
For example, I have three files in my program: main.c, some.h, some.c .
In some.c:
#include "some.h"
static int foo;
[... other functions that uses "foo"]
In some.h:
#ifndef SOME_H_
#define SOME_H_
static int foo;
inline int __attribute__((always_inline))
get_foo(void){
return foo;
}
#endif
In main.c:
#include "some.h"
int bar;
int main(void){
bar = get_foo();
return bar;
}
When I tried to compile, I'm getting following:
warning: 'foo' is static but used in inline function 'get_foo' which is not static
When I tried to put extern static int foo; to some.h, I got:
error: multiple storage classes in declaration specifiers
error: static declaration of 'foo' follows non-static declaration
I need to get values of "static" variables from external file in "inline" functions. I want to keep them "static" to separate from main code, as local variable. Is it a way to do this correctly?
Thank you in advance!
EDIT:
To be more clear: I need to get the the value of a variable in one file (some.c) in another file (main.c) by inline function. If the function get_foo() is NOT "inline", everything works perfect, but it takes more memory and execution time.
In this case, static means the variable foo will be a different foo in each source file. If you change static int foo; to extern int foo; in the header and then have a single int foo; in one .c file, I think the compiler warning will go away and your inline function will work fine.
At file scope, static hides a name from the linker so you effectively have different variables in each file.
extern static int foo; is just a mistake. It means, there is something called foo in some other file that I want you to link to, but the name is hidden. The compiler is just saying "forget it".
There is no point for defining a static variable in a header file. Every time you include that header file you will get a new fresh copy of the variable...
Why you don't just define it as
extern int foo;
This way you will have the variable available from any source that included the header
Your request for inlining is in some way incompatible with the internal linkage of the variable.
You have a static variable which means that this variable is only visible in that file.
On the other you have an inline function. If this function would be inlined somewhere else than in this file, then it would refer to another foo variable, which is probably not what you want; at least the compiler warns you about it. It suggests you to change the visibility of that function to static, as to only be available in the same entity than foo.
In another try, you add extern, but this is incompatible with static visibility, choose, extern or static. Read about linkage and visibility rules in C language, for more information.
You also suggest to add foo in some header, which is not a good idea, headers are reserved for declaration of objects not definition. You are encouraged to add type definition in headers, external declaration of objects; but discouraged from define objects (while not strictly forbidden, this would too often lead to clashes).
If you want to have your variable static in a specific translation unit, an inline function that would "live" in another translation unit would never be able to access this static object. That is why access to static objects from inline functions is not allowed, the semantics of what that would mean is simply not clear.
You can either define an extern function that provides the value of its TU where it is defined, or static function(s) with different instantiations in every TU that provide just the value, there.
Related
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).
This question already has answers here:
How do I use extern to share variables between source files?
(19 answers)
Closed 9 years ago.
Why should I use the extern keyword in the following code:
header.h
float kFloat; // some say I should write 'extern float kFloat;', but why?
file.c
#include <stdio.h>
#include "Header.h"
float kFloat = 11.0f;
main.c
#include <stdio.h>
#include "Header.h"
int main(int argc, const char * argv[])
{
printf("The global var is %.1f\n", kFloat);
return 0;
}
This code works. The global Variable kFloat defaults to external linkage and static lifetime.
Output is:
The global var is 11.0
I don't understand in which case the problem would occur, can anyone give me an example where it would crash?
extern float kFloat;
declares kFloat without defining it.
but:
float kFloat;
also declares kFloat but is a tentative definition of kFloat.
Adding extern just suppresses the tentative definition. In a header file you only want declarations, not definitions.
If the tentative definition is included in several source files, you will end up having multiple definitions of the same object which is undefined behavior in C.
Always put the definition of global variables(like float kFloat;) in the .c file, and put the declarations (like extern float kFloat;) in the header.
Otherwise when multiple .c files include the same header, there will be a multiple definition error.
extern indicates that a variable is defined somewhere in the project (or outside function block) that you want to use. It does not allocate memory for it since you are telling the compiler that this is defined else where.
A variable must be defined once in one of the modules of the program. If there is no definition or more than one, an error is produced, possibly in the linking stage.
Definition refers to the place where the variable is created or assigned storage; declaration refers to places where the nature of the variable is stated but no storage is allocated.
And since it will be accessible elsewhere it needs to be static.
Firstly, it is strange that your code is compiling. It should throw compile time error for double definition of kFloat variable in File.c.
Secondly, if you are trying to use the common variable in two files then it should not be defined in the header.h. You should use extern keyword in header file so that the file which includes the header.h gets to know that it has been defined externally.
Now, you can define the variable globally in any of the c files and then use the variable as a common variable.
Why should I use extern ...?
Well, you shouldn't. Plain and simple. Because you shouldn't use global variables, and they are the only ones that would need the extern keyword.
Whenever you feel tempted to use a global variable, think again. At the absolute maximum, you might need to use a variable with file scope (using the static keyword), typically such a variable would be accompanied by a handful of functions that manipulate/use its value, but the variable itself should not be visible beyond the scope of the file. Usage of global variable only leads to intractably tangled code that is almost impossible to change without introducing a ton of bugs.
I don't want to put the static function definition in two source files(of the same module),
as that's duplicate.
Also I have to declare it as static, because I don't want other modules to use it.
What should I do?
Put the function header in a header file (.h).. can I suggest you find a good C tutorial ?
This sounds like mutually exclusive requirements; you want a single implementation of a function to be shared between two translation units, but you want to declare it static so that it isn't visible to other translation units. Unfortunately, C doesn't offer that kind of granularity; a symbol is either visible to all other translation units or it isn't.
You can fake it by putting the function definition in a header file (declared static), and then #include it in the source files that need it:
#ifndef FUNC_H
#define FUNC_H
static void func() {...}
#endif
The thing is, each translation unit that includes this file will have a redundant implementation of the function. That may or may not be a big deal for you.
Personally, I'd just declare the function normally in its own translation unit, create a header for it, only include the header in the files that need to call that function, and document that function should only be called from those files.
Not sure what do you mean by two files of the same module, but the point of static function is that their scope is limited to file, so the best you can do is to #include one file into the other instead of linking them together. If I got your right...
If the function is short or simple, you might define it (giving also its body) in a header file as a static inline function, e.g.
/* in header.h */
static inline int sum3(int a, int b, int c) { return a+b+c; }
But you really should read a good book on programming in C.
The primary purpose of the static keyword is to create an object that will exist throughout the duration of the program. But all objects declared at file scope ("global") behave in this way, no matter if they are static or not: they have static storage duration.
But it also means that the object cannot be accessed outside the scope it is declared. Functions are declared at file scope ("global") and therefore a static function will only be accessible from the very same file it is declared in. So it doesn't make sense to declare such a function inside a header.
What I think you are trying to do is this:
// function.h
void the_func (void);
// function.c
#include "function.h"
static void the_private_func (void);
void the_func (void)
{
do_things();
do_private_things();
}
static void the_private_func (void)
{
...
};
// some_caller.c
#include "function.h"
...
the_func();
At least this it what makes sense in an object-oriented design.
I'm working on an embedded c project and am having issues with global variable redefinition.
I've split up the function declarations and definitions into a handful of .h and .c files. Many of these functions need access to global variables, which are defined in global_vars.h. Therefore, at the beginning of the header files, inside the #ifndef, #define section, "global_vars.h". If I don't, as you might imagine I get a bunch of undefined variable errors.
However, even though global_vars.h has the #ifndef _GLOBAL_VARS_H_ #define... #endif, I get redefinition errors for all the global variables. My guess is that when the linker tries link the various object files, it sees the redefinition due to the #include "global_vars.h" in all the "blah_blah.h" files. It was my understanding, though, that the #ifndef... takes care of this issue.
Is there something I'm overlooking?
Thanks in advance
The linker never sees anything in the global_vars.h file, ever, unless -- bad news! -- some of the globals are actually defined in that file. global_vars.h should hold only declarations of those global variables, never (well, almost never) their definitions.
In global_vars.h, you should have declarations like:
extern int some_global;
You are not allowed to have:
int some_global;
If you have definitions in global_vars.h then, yes, they'll be multiply defined at link time because each of the .c files that #includes global_vars.h will have its own definition of each defined variable.
All of the definitions of the extern globals must be in some .c file, for sure. Usually it doesn't matter which .c file. Often all of the global-variable definitions are in a file called (surprise!) global_vars.c.
So make sure there aren't any global-variable definitions in global_vars.h and you'll be in good shape.
Is not a good idea to define globals in an H file. Better if you do that in a C or C++ file and you include and H file in other modules with those globals as externals.
Like this>>>
My module c file
unsigned short int AGLOBAL = 10; // definer and initializer
void MyFunc(void)
{
AGLOBAL+=1; // no need to include anything here cause is defined above
// more .....
}
My H file globals.h
// this is to include only once
#ifndef MYH
#define MYH
extern unsigned short int AGLOBAL; // no value in here!
#endif
Other module c file
#include globals.h
char SomeOtherFunc(void)
{
AGLOBAL+=10; // ok cause its defined by globals.h
// do more....
}
So let me start with saying that extern keyword applies to C variables (data objects) and C functions. Basically extern keyword extends the visibility of the C variables and C functions. Probably that’s is the reason why it was named as extern.
Use of extern with C functions. By default, the declaration and definition of a C function have “extern” prepended with them. It means even though we don’t use extern with the declaration/definition of C functions, it is present there.
For example, when we write.
int foo(int arg1, char arg2);
There’s an extern present in the beginning which is hidden and the compiler treats it as below.
extern int foo(int arg1, char arg2);
Same is the case with the definition of a C function (Definition of a C function means writing the body of the function). Therefore whenever we define a C function, an extern is present there in the beginning of the function definition. Since the declaration can be done any number of times and definition can be done only once, we can notice that declaration of a function can be added in several C/H files or in a single C/H file several times. But we notice the actual definition of the function only once (i.e. in one file only). And as the extern extends the visibility to the whole program, the functions can be used (called) anywhere in any of the files of the whole program provided the declaration of the function is known. (By knowing the declaration of the function, C compiler knows that the definition of the function exists and it goes ahead to compile the program).
So that’s all about extern with C functions.
Declaration can be done any number of times but definition only once.
“extern” keyword is used to extend the visibility of variables/functions().
Since functions are visible through out the program by default. The use of extern is not needed in function declaration/definition. Its use is redundant.
When extern is used with a variable, it’s only declared not defined.
As an exception, when an extern variable is declared with initialization, it is taken as definition of the variable as well.
My question is about when a function should be referenced with the extern keyword in C.
I am failing to see when this should be used in practice. As I am writing a program all of the functions that I use are made available through the header files I have included. So why would it be useful to extern to get access to something that was not exposed in the header file?
I could be thinking about how extern works incorrectly, and if so please correct me.
Also.. Should you extern something when it is the default declaration without the keyword in a header file?
extern changes the linkage. With the keyword, the function / variable is assumed to be available somewhere else and the resolving is deferred to the linker.
There's a difference between extern on functions and on variables.
For variables it doesn't instantiate the variable itself, i.e. doesn't allocate any memory. This needs to be done somewhere else. Thus it's important if you want to import the variable from somewhere else.
For functions, this only tells the compiler that linkage is extern. As this is the default (you use the keyword static to indicate that a function is not bound using extern linkage) you don't need to use it explicitly.
extern tells the compiler that this data is defined somewhere and will be connected with the linker.
With the help of the responses here and talking to a few friends here is the practical example of a use of extern.
Example 1 - to show a pitfall:
stdio.h:
int errno;
myCFile1.c:
#include <stdio.h>
// Code using errno...
myCFile2.c:
#include <stdio.h>
// Code using errno...
If myCFile1.o and myCFile2.o are linked, each of the c files have separate copies of errno. This is a problem as the same errno is supposed to be available in all linked files.
Example 2 - The fix.
stdio.h:
extern int errno;
stdio.c:
int errno;
myCFile1.c:
#include <stdio.h>
// Code using errno...
myCFile2.c:
#include <stdio.h>
// Code using errno...
Now if both myCFile1.o and MyCFile2.o are linked by the linker they will both point to the same errno. Thus, solving the implementation with extern.
It has already been stated that the extern keyword is redundant for functions.
As for variables shared across compilation units, you should declare them in a header file with the extern keyword, then define them in a single source file, without the extern keyword. The single source file should be the one sharing the header file's name, for best practice.
Many years later, I discover this question. After reading every answer and comment, I thought I could clarify a few details... This could be useful for people who get here through Google search.
The question is specifically about using extern functions, so I will ignore the use of extern with global variables.
Let's define 3 function prototypes:
// --------------------------------------
// Filename: "my_project.H"
extern int function_1(void);
static int function_2(void);
int function_3(void);
The header file can be used by the main source code as follows:
// --------------------------------------
// Filename: "my_project.C"
#include "my_project.H"
void main(void) {
int v1 = function_1();
int v2 = function_2();
int v3 = function_3();
}
int function_2(void) return 1234;
In order to compile and link, we must define function_2 in the same source code file where we call that function. The two other functions could be defined in different source code *.C or they may be located in any binary file (*.OBJ, *.LIB, *.DLL), for which we may not have the source code.
Let's include again the header my_project.H in a different *.C file to understand better the difference. In the same project, we add the following file:
// --------------------------------------
// Filename: "my_big_project_splitted.C"
#include "my_project.H"
void old_main_test(void){
int v1 = function_1();
int v2 = function_2();
int v3 = function_3();
}
int function_2(void) return 5678;
int function_1(void) return 12;
int function_3(void) return 34;
Important features to notice:
When a function is defined as static in a header file, the compiler/linker must find an instance of a function with that name in each module which uses that include file.
A function which is part of the C library can be replaced in only one module by redefining a prototype with static only in that module. For example, replace any call to malloc and free to add memory leak detection feature.
The specifier extern is not really needed for functions. When static is not found, a function is always assumed to be extern.
However, extern is not the default for variables. Normally, any header file that defines variables to be visible across many modules needs to use extern. The only exception would be if a header file is guaranteed to be included from one and only one module.
Many project managers would then require that such variable be placed at the beginning of the module, not inside any header file. Some large projects, such as the video game emulator "Mame" even require that such variables appears only above the first function using them.
In C, extern is implied for function prototypes, as a prototype declares a function which is defined somewhere else. In other words, a function prototype has external linkage by default; using extern is fine, but is redundant.
(If static linkage is required, the function must be declared as static both in its prototype and function header, and these should normally both be in the same .c file).
A very good article that I came about the extern keyword, along with the examples: http://www.geeksforgeeks.org/understanding-extern-keyword-in-c/
Though I do not agree that using extern in function declarations is redundant. This is supposed to be a compiler setting. So I recommend using the extern in the function declarations when it is needed.
If each file in your program is first compiled to an object file, then the object files are linked together, you need extern. It tells the compiler "This function exists, but the code for it is somewhere else. Don't panic."
All declarations of functions and variables in header files should be extern.
Exceptions to this rule are inline functions defined in the header and variables which - although defined in the header - will have to be local to the translation unit (the source file the header gets included into): these should be static.
In source files, extern shouldn't be used for functions and variables defined in the file. Just prefix local definitions with static and do nothing for shared definitions - they'll be external symbols by default.
The only reason to use extern at all in a source file is to declare functions and variables which are defined in other source files and for which no header file is provided.
Declaring function prototypes extern is actually unnecessary. Some people dislike it because it will just waste space and function declarations already have a tendency to overflow line limits. Others like it because this way, functions and variables can be treated the same way.
Functions actually defined in other source files should only be declared in headers. In this case, you should use extern when declaring the prototype in a header.
Most of the time, your functions will be one of the following (more like a best practice):
static (normal functions that aren't
visible outside that .c file)
static inline (inlines from .c or .h
files)
extern (declaration in headers of the
next kind (see below))
[no keyword whatsoever] (normal
functions meant to be accessed using
extern declarations)
When you have that function defined on a different dll or lib, so that the compiler defers to the linker to find it. Typical case is when you are calling functions from the OS API.