static function declarations in header files - c

I have a static function in a source file that is used by other functions in that same source file. Is it fine to put the declaration for that static function in the header file, even though that header file will be included into other source files? Example:
/* foo.c */
#include "foo.h"
/* exported function; calls g */
void f(void) {
g();
}
static
void g(void) {
/* do something... */
}
/* foo.h */
void f(void);
void g(void);
/* main.c */
#include "foo.h"
int main(void) {
f();
}

Is it fine to put the declaration for that static function in the header file, even though that header file will be included into other source files?
No. Consider the conflict the other source files would have if they had a function/object/macro of the same name.
Even without conflict, an "unused function" warning may occur. #Adrian Mole
By putting static void g(void) in the .h file, it adds an unnecessary potential name conflict.
Simply declare/define that static function at the top of the .c in which it is used.

Is it fine to put the declaration for that static function in the
header file, even though that header file will be included into other
source files?
No. becuse it does not make any sense. and why?
In C, functions are global by default. Unlike global functions in C, access to static functions is restricted to the file where they are declared! Therefore, when we want to restrict access to functions, we make them static.
Another reason for making functions static can be reuse of the same function name in other files. so declaring them static in the header file can cause to name collisons in other source files.
In header files we declare our API functions those we want to expose only. in c files we declare usually auxilary functions as static functions for restricting the scope of those aux functions to the c file only

Related

Constructor in C - Declare (in .h) and define (in .c) It does not behave as expected

I declare a constructor in constructor.h and define it in constructor.c.
I will show both files:
constructor.h
void begin(void) __attribute__((constructor));
constructor.c
void begin(void) {
printf("INIT");
}
My main.c, which has code which uses the function, is including constructor.h.
Previously I defined and declared begin in the same .h file and that worked fine.
Now I try to separate code, declare in .h and define in .c, and it is not working anymore.
Why could that be?
To make the compiler be aware of the content of the header while compiling the .c file, you need to include the header in the code file.
#include "constructor.h"
/* ... */
Also you should implement the function as declared:
/* ... */
void begin(void) __attribute__((constructor)) {
printf("INIT");
}

Errors due to static inline version of a earlier non-static non-inline function

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 */}

Scope of Function access in C

Suppose I have a function that I want to use internally such as private in Java or C++, but I am writing in C. In this case, I have a header file and a c file implementation and the c file has several functions that should not be available to the end user. Is it ok for me to not declare these functions in the header file in order to prevent access to them or is this bad practice / is there a better way?
That's pretty much what you would do in this case and add static to the declared functions. You would declare your public functions in the .h file and the private functions in the .c file.
Let's say you had a .h and .c file as such:
SomeFile.h
void doSomething1(void);
void doSomething2(void);
SomeFile.c
static void doSomething3(void);
static void doSomething4(void);
//These functions can be called by anyone
void doSomething1(void)
{
//function guts here
}
void doSomething2(void)
{
//function guts here
}
//These functions can only be called inside this file
static void doSomething3(void)
{
//function guts here
}
static void doSomething4(void)
{
//function guts here
}
Yes its ok to make some of the functions not available in the header file.
The other options are to separate the header files into 2. One for internal use and other for external user.
Apart from that also you can declare the functions static making them not visible outside the file scope
Declare these functions directly in the .c file as static functions and provide the definitions of the functions in the same file:
Ìn the .c file:
static void internal_func1(void);
static int interal_func2(int a);
static void internal_func1(void)
{
/* body of internal_func1 */
}
static int interal_func2(int a)
{
/* body of internal_func2 */
}
Adding the static keyword makes these functions invisible to other source files (the function identifier will have internal linkage).
Make such internal function static and keep it just in .c file.
See static functions:
If a function is to be called only from within the file in which it is declared, it is appropriate to declare it as a static function. When a function is declared static, the compiler will now compile to an object file in a way that prevents the function from being called from code in other files.
Or in the C standard:
6.2.2 Linkages 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.1
1 A function declaration can contain the storage-class specifier static only if it is at file scope ....

C - extern, static, include

Scoping in C is confusing as hell. I have a variable: "int qwe". This var should be visible in one or more files - f1.c in this case, but not the another f2.c .
Say i have: main.c, f1.c, f2.c, header.h
main:
call f1();
call f2();
header:
#ifndef HEADER_INCLUDED
#define HEADER_INCLUDED
int qwe = 1;
void f1();
void f2();
#endif // HEADER_INCLUDED
f1.c:
#include <stdio.h>
extern int qwe;
void f1(){
printf("In f1: %d\n", qwe);
}
f2.c:
#include <stdio.h>
static int qwe = 2;
void f2(){
printf("In f2: %d\n", qwe);
}
Now this gets confusing. There is definition and declaration. I have defined qwe in the header, declared it in f1.c. Is that correct? Should definition happen in header and declaration in f1.c instead? I tried the latter case, but got an error - "multiple definition of qwe". When i removed the #include directive from f1.c, it worked... It also works when i remove the extern keyword. Is extern redundant?
f2.c i guess it's ok and behaves as expected, or is it? But if i put an #include with header, it breaks. Why is that?
When should i use #include in source files? If i don't include it f1.c or f2.c it works...
Also, if i define a variable as static inside a function, like static int i = 0; This variable will not be destroyed when function exist, it will keep it's memory and data. And next time that same function gets called, will have access to it, right? But the var won't be reinitialized to 0, i.e. the line where is defines won't execute. Correct?
Life stomps me :(
In the header, declare the variable. In e.g f1.c, define the variable, e.g. int qwe = 1; // at global scope.
In all files that want to see/change qwe, include the header that declares the variable. Easy-peasy.
You need to declare the variable in the header, and define it in one and only one C file.
In C, you cannot have a variable that doesn't "belong" to a given translation unit (source file). So it must be defined by exactly one translation unit in the whole program.
When you declare a variable as extern, you're telling the compiler the symbol is (possibly) external to your translation unit (c file).
It's probably also worth noting that when you try to declare a variable without extern, the variable is also defined, e.g.:
/* Declares, but does not defines external symbol 'foo' */
extern int foo;
/* Both declares AND defines bar */
int bar;
This is also different from how functions work to where the "default" syntax for declaration does NOT define a function:
/* Declare, but don't define spam */
void spam(void);
/* Declare, but don't define eggs */
extern void eggs(void);
/* Declare & define 'cheese' */
void cheese(void){ return; }
So your example should look more like this:
qwe.h:
#ifndef QWE_H
#define QWE_H
/* Declare qwe here */
extern int qwe;
#endif
f1.c:
/* DEFINE qwe here */
int qwe = 1;
f2.c:
#include "qwe.h" /*header includes the `extern int qwe` declaration */
void my_function(void)
{
/* use external symbol here! */
qwe = 10;
}
The scoping system isn't that confusing. The rule is this:
if you define something in a .c file EVERY other .c file in your program can access it (it is put in the global namespace).
if you specify static in front of its definition then only things in the SAME file can see it. This should be your default position for all functions and variables you don't want other .c files to be able to access.
It is very important to remember that extern only tells the compiler that the variable/function in question is not defined in the current file. This prevents the compiler for otherwise issuing an error because it can't find the symbol, but it has nothing to do with scoping - your .c file sees everything in the global namespace and if you have not followed the second part of the rule you will quickly find out about this at link time.
Header files similarly have nothing to do with scoping. They are just convenient places to put a bunch of extern statements and macros.
In C, you should use the header file in general to declare the data but not define the data. You don't want to define global data in a header because it will then be redundantly defined in multiple modules. The header indicates to multiple modules the existence of some data or function somewhere and what its type is, as well as common constants and macros (#defines). Outside of that, things in C are very simple. Just about anything is, technically, global unless you declare it static, keeping it scoped to the module it's defined in. The extern declarations for data in the headers and the function prototypes help the compiler know that these items are being accessed by a particular module and what the data types are for access so that the correct code can be generated.
You have:
Two functions f1 and f2 that are defined in separate modules but used in main. So these need to be declared in a header file.
A global data item qwe being used in more than one module.
A static qwe used in one module.
Assuming you want this done with one header file (you might need separate ones for f1, f2, and global data - see below), you could set up
your header as:
#ifndef MY_HEADER_H
#define MY_HEADER_H
extern int qwe;
void f1(void);
void f2(void);
#endif // MY_HEADER_H
Then in your main.c:
...
#include "my_header.h"
int qwe; // This is global and can be accessed from other modules
void main(...)
{
// call f1
// call f2
...
I just defined the global variable, qwe, in main.c arbitrarily. If you have a few globals, you can define them in their own glob_data.c module, for example, and have it's own header, glob_data.h, to declare them. Any other module that needs to access them would include the glob_data.h header so that compilation can properly be done on that module to access that data. Keeping the global data in separate headers helps with cases like you have where you have a static instance of the data versus the global, which are in conflict. You can avoid including the data header file for that global item when you want to compile with the static item.
Then in your C file, f1.c:
...system headers included...
#include "my_header.h"
void f1() {
printf("In f1: %d\n", qwe);
}
And in f2.c:
...system headers included...
#include "my_header.h" // Only if it doesn't contain `extern int qwe;`
static int qwe = 2; // This hides the global qwe and is known only
// to f2.c
void f2(){
printf("In f2: %d\n", qwe);
}
As I mentioned above, you might want to separate your function prototypes and your global data declaration in separate headers. That way, you can include only what's needed in each module and avoid conflicts, such as when you have a static int qwe; versus the global int qwe;.
I have defined qwe in the header, declared it in f1.c. Is that correct?
No, it should be the other way around. You are supposed to have a definition of a global variable in a single translation unit (that's geek speak for a .C file) but you may declare it in as many translation units as you wish. Since headers potentially get included from many translation units, declarations go in the headers.
When should i use #include in source files?
You do it when the header has anything that is needed for your translation unit to compile, with very few exceptions. Note that in some situations it may be necessary or desirable to make a forward declaration manually without including the header.
Also, if I define a variable as static inside a function, like static int i = 0; This variable will not be destroyed when function exist, it will keep it's memory and data.
That is correct, the static variable inside the function will be assigned the initial value only once, and retain the value that you assign to it for as long as your program continues to run.

Warnings while organising variables and functions in C over multiple header and source files

For the first time i was trying to write an actual professional C code for a simple program.
1)I made a header file name Essential_data.h and declared all my functions and global variables in that. I had declared all my variables as extern.. And all function declaration were made normally
eg:
void test ();
extern int x;
2)Then i made another header file named main_data.h and defined all my global variables there.
for eg:int x;
3)I then made corresponding source files containing the definition of the respective functions and included main_data.h in sourcefiles that needed that global variable.
thats all. After when i compiled the project i got many warnings for all functions as
Implicit declaration of function test [-Wimplicit-function-declaration]
so after that i did the following
1) I put an extern in front of the functions declarations in Essential_data.h.
for eg:
extern void test();
2) in the main_data.h i declared the functions normally and wrote
void test ();
both the times my Essential_data.h was in the main function only and no where else.
And then recompiled and later all the warnings disappeared.
So was that the right method or is there any other way of organising them more efficiently?
You should have:
One or more .h files containing extern declarations (functions and objects). These files needs to be included by the .c files that need those symbols. You shouldn't have multiple declarations (each identifier should be declared exactly once)
One or more .c files in which you define the functions and objects
In your example:
/* essential_data.h */
void test ();
extern int x;
/* something.c */
#include "essential_data.h"
int x;
void test()
{
/* ... */
}
/* main.c */
#include "essential_data.h"
/* ... */

Resources