Reputation: 3
Can the headers files in C include variables?
I am a beginner in programming; started with C, and I know the importance of precision especially in the first steps of the learning process
Upvotes: 0
Views: 122
Reputation: 43498
Including files is done by the preprocessor before even attempting to compile the code and it simply does text replacement – it puts the contents of the included file in the current unit that is going to be passed to the compiler. The compiler then sees the concatenated output and no #include
directives at all.
With that said, technically you can include anything that is valid C code.
The good practice, however, is that only type definitions, #define
s, function declarations (not definitions) and data declarations (not definitions) should be in a header. A function declaration is also called a prototype and merely specifies the function signature (its return type, name and parameters). Data declarations look very similar to data definitions, but have an extern
storage class specifier and cannot be initialised:
extern int a; // declares "a" but does not define it
extern int a = 0; // defines "a" (initialisation requested), the extern is redundant
int a; // a tentative definition (no initialisation but "a" is zeroed)
Why is defining functions and data in a header file frowned upon? Because at link time, different units that have included the same header files will have the same symbols defined and the linker will see duplicate definitions of some symbols.
Also consider that a header is a kind of a "public" interface for the rest of the project (world?) and not every function that is defined in the source file needs to have a declaration there. It is perfectly fine to have internal types and static
functions and data in the source file that never get exposed to the outside world.
Upvotes: 1
Reputation: 123458
Yes, header files may include variable declarations, but you generally don't want to do that because it will introduce maintenance headaches over time, especially as your code gets larger and more complex. Ideally, functions should share information through parameters and return values, not by using such "global" data items.
There are times when you can't avoid it; I haven't done any embedded programming, but my understanding is that using globals is fairly common in that domain due to space and performance constraints.
Ideally, headers should be limited to the following:
But suppose you do create a header file with a variable declaration, like so:
/**
* foo.h
*/
int foo;
and you have several source files that all include that header1:
/**
* bar.c
*/
#include "foo.h"
void bar( void )
{
printf( "foo = %d\n", foo );
}
/**
* blurga.c
*/
#include "foo.h"
void blurga( void )
{
foo = 10;
}
/**
* main.c
*/
#include "foo.h"
int main( void )
{
foo = 5;
blurga();
bar();
return 0;
}
Each file will contain a declaration for foo
at file scope (outside of any function). Now you compile each file separately
gcc -c bar.c
gcc -c blurga.c
gcc -c main.c
giving you three object files - bar.o
, blurga.o
, and main.o
. Each of these object files will have their own unique copy of the foo
variable. However, when we build them into a single executable with
gcc -o foo main.o bar.o blurga.o
the linker is smart enough to realize that those separate declarations of foo
are meant to refer to the same object (the identifier foo
has external linkage across those translation units). So the foo
that main
initializes to 5
is the same foo
that blurga
sets to 10
, which is the same foo
that bar
prints out.
However, if you change the declaration of foo
to
static int foo;
in foo.h
and rebuild your files, then those separate declarations will not refer to the same object; they will remain three separate and distinct objects, such that the foo
that main
initializes is not the same foo
that blurga
sets to 10
, which is not the same foo
that bar
prints out (foo
has internal linkage within each translation unit).
If you must use a global variable between several translation units, my preferred style is to declare the variable in the header file as extern
2
/**
* foo.h
*/
extern int foo;
and then define it in a corresponding .c file
/**
* foo.c
*/
int foo;
so only a single object file creates an instance of foo
and it's crystal clear that you intend for other translation units to make use of it. The declaration in the header file isn't necessary for the variable to be shared (the foo
identifier has external linkage by simple virtue of being declared in foo.c
outside of any function and without the static
keyword), but without it nobody else can be sure if you meant for it to be visible or if you just got sloppy.
Edit
Note that headers don't have to be included at the top of a file; you can be perverse and put an #include
directive within a function body
void bar( void )
{
#include "foo.h"
// do stuff with foo
}
such that int foo;
will be local to the function, although that will likely earn you a beating from your fellow programmers. I got to maintain code where somebody did that, and after 25 years it still gives me nightmares.
extern
keyword tells the compiler that the object the identifier refers to is defined somewhere else.
Upvotes: 0
Reputation: 167
Basically in header files, we can declare variables point to be noted only declaration is allowed there, do not define
let me clear.
int a=10; // definition
extern int a; //declaration - it can be used in another file if u include this header file.
you can also define the macro and declare the functions in header file.
Upvotes: 0