initializing a static variable in header - c

I am new in programming in C, so I am trying many different things to try and familiarize myself with the language.
I wrote the following:
File q7a.h:
static int err_code = 3;
void printErrCode(void);
File q7a.c:
#include <stdio.h>
#include "q7a.h"
void printErrCode(void)
{
printf ("%d\n", err_code);
}
File q7main.c:
#include "q7a.h"
int main(void)
{
err_code = 5;
printErrCode();
return 0;
}
I then ran the following in the makefile (I am using a Linux OS)
gcc –Wall –c q7a.c –o q7a.o
gcc –Wall –c q7main.c –o q7main.o
gcc q7main.o q7a.o –o q7
the output is 3.
Why is this happening?
If you initialize a static variable (in fact any variable) in the header file, so if 2 files include the same header file (in this case q7.c and q7main.c) the linker is meant to give an error for defining twice the same var?
And why isn't the value 5 inserted into the static var (after all it is static and global)?
Thanks for the help.

static means that the variable is only used within your compilation unit and will not be exposed to the linker, so if you have a static int in a header file and include it from two separate .c files, you will have two discrete copies of that int, which is most likely not at all what you want.
Instead, you might consider extern int, and choose one .c file that actually defines it (i.e. just int err_code=3).

When you declared a variable as a static it has only scope within a file ie.., it can be accessed only within a file.
When you declare a static variable in a header file and include this header file in two .c file, then you are creating two different
memory for two different ".c" files
When you print err_code directly in the Main function you would see its value as 5 instead 3,
but you are calling a function printErrCode which is defined in a different file "q7a.c" for which err_code has a different memory location
in which err_code memory is still 3 and it not updated and that is why you are getting the value as 3 instead of 5.
Since two memory is created and err_code is considered as two different variables having different memory with different file scope you will not see any linking errors.

The static variables do not have external linkage which means they cannot be accessed outside the translation unit in which they are being defined. So in your case when q7.h is #include'ed in both translations units q7a.c and q7main.c ... two different copies exists in their corresponding .o files. That is why linker does not report error becuase both copies are not seen by linker while doing external symbol linkage.

While doing small research came to know that we can declare variable in Header file but in one of the source file includes that should have definition for that variable.
Instead if we define a variable in header file. in the source files where this header file included, definitions will be created which causes multiple definitions.
A static variable should be declared with in the file where we use it shouldn't be exposed to header file.
Hope I am giving right information. If I am wrong feel free to correct my statements in your comments.

Related

#include "another_source.c", use inline function( ) there, then does the function( ) become inline as well?

Let's say I have two files named "AA.c", "BB.c"
/* in AA.c */
inline void AA(void) __attribute__((always_inline));
void AA()
{
/* do something */
}
and then
/* in BB.c */
#include "AA.c"
extern void funcAA(void);
int main(void)
{
funcAA();
return 0;
}
does funcAA( ) also become inline???
no matter the answer is yes or no, could you explain some more about the under the hood??
including a .c file is equivalent of copying and pasting the file contents directly in the file which includes that, exactly like if the function was directly defined in the including file.
You can see what the compiler is going to compile by trying to compile your file with -E flag (preprocessor output). You'll see your function pasted-in.
So it will be inline just because of the inline keyword, and forced with the always_inline attribute even if the compiler would have refused to inline it because of function size for instance.
Word of advice: know what you're doing when including a .c file from another one. Some build systems/makefiles just scan the directories looking for files called *.c so they can compile them separately. Putting a possibly non-compiling C file there can make the build fail, and if it builds, you could have duplicate symbols when linking. Just don't do this.
If you want to do this, put your function in a .h file and declare it static so it won't fail the link if included in many .c files (each function will be seen as different)

C file extension if you include C file inside another

I have a C file with all static functions, related to one and same sub-task.
Some of the functions are quite long - 20-30 lines.
I want to include it in another C file.
What must be the file extension (in order things to considered professional). Shall I do it as H file?
20-30 lines isn't long. 200-300 lines is getting long but still doesn't warrant a separate file.
Most projects would be unmanageable if 20 line functions had their own file.
Just put the functions in the .c file they're used in and declare them static.
I don't know what build tool you're using but traditional 'make' might get confused by .c unless you introduce further rules and discipline.
If you do put them in another file give it the .inc suffix as others suggest.
I have generally only seen people do this when the .inc is maintained by an external tool.
If you really need to share the same static methods across multiple c files (for compiler optimization?), you should place them in a .c-file and not in a .h file.
If you don't need to make those methods static, you should really place them in a single .c module which is liked to the binary and only share the definitions across the modules using them.
Example
If you really have to share the static functions and you have a really good reason
static_functions.c (I'd name it static_functions.inc.c, but that's personal flavour)
static int max(int a, int b) {
if (a > b)
return a;
return b;
}
module-x.c for some x
#include "static_functions.c"
int use_max() {
return max(1,2);
}
Compile module-x.c only.
If you don't really need static versions
internal_functions.h
#ifndef internal_functions_h
#define internal_functions_h
int max(int a, int b);
#endif
internal_functions.c
#include "internal_functions.h"
int max(int a, int b) {
if (a > b)
return a;
return b;
}
module-x.c for some x
#include "internal_functions.h"
int use_max() {
return max(1,2);
}
And then compile and link together internal_functions.c and module-x.c.
To have the definitions local only, you don't need to use or ship your internal_functions.h elsewhere.
include C file inside another
No, not the way. Conventionally,
.c [source files] are meant to be compiled and linked together
.h [Header files] are there to be included.
C file with all static methods [] Shall I do it as H file?
No. Ideally header files [.h] are not supposed to contain any definition. There should be declarations only. Otherwise, if a header file .h contains definitions and you've got included them more than once, you'll be facing multiple definition issue.
I have a little doubt regarding
C file with all static methods.
If all the methods [functions] are static, how to use them, anyway?
However, the way for you will be taking all the related .c files, compile and link them together to form the final binary.
Do not include separate c files. Just compile them separately as they are.
Suppose you have two files with code: main.c and include.c.
Rather than having #include "include.c" inside main.c, when you compile link the object files:
gcc main.c include.c

Two static variables in same name(two different file) and extern one of them in any other file

Declaring a variable as static in one file and do a extern declaration in another file - i thought this will give an error while linking as the extern variable will not be seen in any object, as the one which declared in other file was with qualifier static. But somehow the linker(renesas) didn't show any error and created executable.
If the above usecase was correct, what will happen if 2 variables be declared as static in 2 different files and another in another file with extern declaration? In this case 2 different memories will be created in 2 different objects, but which one of the variable will be linked for other variable was declared as extern in another file(as both the variable name are same)??
file1.c
static int test_var;
fn1()
{
test_var = 1;
}
file2.c
static int test_var;
fn2()
{
test_var = 2;
}
file3.c
extern int test_var;
fn3()
{
int x;
x = test_var;
}
In your example, file3.c has absolutely no access to variable test_var in either file1.c or file2.c. You should get a linking error if test_var is not declared within the scope of file3.c.
In file1.c and file2.c, the keyword static means the variable test_var is file scope. That means this variable only accessible in the the file where it's declared.
In the file3.c, the keyword extern means the variable is declared in other file.
When the compiler compile the file3.c, it will mark the variable test_var is in other object file, and doesn't care where is it. So this file can be compiled, and no errors occurred.
But when the linker process this object files, it will found that no variable named as test_var can be link to file3, an error will be shown.
The answer is probably in a way you have configured linker. If you are linking library everything will be OK here and file3.o module will have test_var reference as UNDEFINED.
If you're linking application from this 3 modules you will fail just because absence of main() routine definition and unresolved external will be considered even less evil. :-)
Just to check it please examine appropriate *.o modules symbol tables in your build process and then final result. Having such approach you will find the reason of your strange build behavior.

how to define a variable in one file and use it in another one

The question may be very basic but I am not getting clue anyways ...
I have two files ...
and I am mentioning what I want to do .
file 1
...
j = data->alloc_len;
...
file 2
...
for(i=0;i<j;i++)
...
Its clear from above I want to assign value to a variable in one file and want to use that value in other file.
I tried #include "file1.c" in file2.c but it is giving lot of re-declaration errors.
I tried creating a seperate header file which only have one line int j and then included it in both files using extern but no benefit again.Although I think header files are meant for where i can create and assign a value to a variable in one file and then this value can be propogated to all other files by including this one.
May be I am wrong but I need it soon so please help me ...Thnx in advance.
Limitation -
The value can be assigned only through file1.c because data structure is declared and defined here only.I can not provide a value to variable j in a header file .
EDIT :
Although I mentioned but I think I could not clear my question.I have tried using it header files.
For debugging purpose I tried this ..
sample.h
extern int j;
file1.c
#include "sample.h"
int j=245;
file2.c
#include "sample.h"
printf("%d",j);
but its getting error .
Error I am getting is :
Couldn't open module sample.so, tried:
sample.so: cannot open shared object file: No such file or directory
./sample.so.so: cannot open shared object file: No such file or directory
/usr/local/lib/sendip/sample.so.so:
cannot open shared object file: No such file or
directory
/usr/local/lib/sendip/sample.so: undefined symbol: j
*none of the file contains main function actually *
Actually it is a very large project and I am using Makefile and all files will be linked at run time.
In short,the execution could be understood as there is a main.c file which contains main which in turns call file1.c and which in turn calls file2.c
About descriptive names I would say they are just for showing here otherwise I am already using descriptive name.
You could put this in a header file:
extern int j;
and only declare the "real" j in file1.c. If file2.c includes that header, then it can use variable j.
But, use descriptive variable names a the very least for globals. And you should avoid globals as much as you can, they are a liability in the long term, IMO.
(You could consider something like making a function in file1.c that returns that value. This has the advantage of assuring that j is controlled in file1.c, and only read in other places, limiting the complexity of understanding who "owns" that variable.)
like this
in the c file you define the variable say file1.c you write
int j;
...
j = data->alloc_len;
a header for your file1.h would contain
extern int j;
this header you include in file2.c
#include "file1.h"
but i would suggest using a more descriptive variable name.
#include "file1.c" is almost never the correct solution to a problem. Invariable you want to be declaring things in header files and then defining them in just a single source file.
file1.h
extern int j;
file1.c
#include "file1.h"
j = data->alloc_len
file2.c
#include "file1.h"
if (j>0)
...
Having said all of this, I would strongly council you to pass values as parameters rather than use global state. Global state is evil. Avoid it like the plague.

multiple definiton of function-error in kernel-file

Hey guys.
What I'm currently trying to do is to port the tool DigSig to a CentOS-Kernel which seems to lack a few important crypto-functions for DigSig.
So the port this I just a newer /linux/crypto.h which has the functionality I need plus I added this little code:
void kzfree(const void *p) {
size_t ks;
void *mem = (void *)p;
if (unlikely(ZONP(mem)))
return;
ks = ksize(mem);
memset(mem, 0, ks);
kfree(mem);
}
because my kernel I'm working on does not have kzfree yet.
Now, when I try to compile DigSig, this is the output:
/home/Chris/dsTest/dsi_sysfs.o: In function `kzfree':
/usr/src/kernels/2.6.18-194.32.1.el5-i686/include/linux/crypto.h:114: multiple definition of `kzfree'
/home/Chris/dsTest/digsig.o:/usr/src/kernels/2.6.18-194.32.1.el5-i686/include/linux/crypto.h:114: first defined here
/home/Chris/dsTest/digsig_cache.o: In function `kzfree':
/usr/src/kernels/2.6.18-194.32.1.el5-i686/include/linux/crypto.h:114: multiple definition of `kzfree'
/home/Chris/dsTest/digsig.o:/usr/src/kernels/2.6.18-194.32.1.el5-i686/include/linux/crypto.h:114: first defined here
/home/Chris/dsTest/digsig_revocation.o: In function `kzfree':
/usr/src/kernels/2.6.18-194.32.1.el5-i686/include/linux/crypto.h:114: multiple definition of `kzfree'
/home/Chris/dsTest/digsig.o:/usr/src/kernels/2.6.18-194.32.1.el5-i686/include/linux/crypto.h:114: first defined here
/home/Chris/dsTest/dsi_sig_verify.o: In function `kzfree':
/usr/src/kernels/2.6.18-194.32.1.el5-i686/include/linux/crypto.h:114: multiple definition of `kzfree'
/home/Chris/dsTest/digsig.o:/usr/src/kernels/2.6.18-194.32.1.el5-i686/include/linux/crypto.h:114: first defined here
Of course, all is covered by #ifndef-Guards, so I just cannot understand why he is defining this function multiple times...
Any ideas?
Your include file gets included in multiple places.
This is not compile time error. But rather a linked time error.
Each of your file got compiled and produced following .o files
/home/Chris/dsTest/dsi_sysfs.o
/home/Chris/dsTest/digsig_cache.o
/home/Chris/dsTest/digsig_revocation.o
/home/Chris/dsTest/dsi_sig_verify.o
Now while linking them together it finds multiple definition of kzfreez, one each in above .o files because their corresponding c files included
/usr/src/kernels/2.6.18-194.32.1.el5-i686/include/linux/crypto.h
You have ifdef guarded the file, but that only prevents inclusion of .h file in same c file (translation units) not across different c files.
You should write the function in c file and add in in make files, so that it gets compiled separately and linked. And only add declaration in crypto.h . (For testing you can add definition in crypto.c and declaration in crypto.h).

Resources