Mihai Ardelean
Mihai Ardelean

Reputation: 3

C --> headers & variables

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

Answers (3)

Blagovest Buyukliev
Blagovest Buyukliev

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, #defines, 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

John Bode
John Bode

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:

  • Macro definitions
  • Type definitions
  • Function declarations

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 extern2

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


1. Please don't write code like this; it's only to illustrate the concept of linkage.
2. The extern keyword tells the compiler that the object the identifier refers to is defined somewhere else.

Upvotes: 0

Mike
Mike

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

Related Questions