Why such warning even though type is specified in .h file

67 Views Asked by At

There are 2 files libtest.h and libtest.c

libtest.h

int a;

libtest.c

#include "libtest.h"

a = 10;

When I compile libtest.c

cc -c libtest.c

libtest.o is generated but I get this warning. What is the reason ?

libtest.c:3:1: warning: type specifier missing, defaults to 'int' [-Wimplicit-int]
a = 10;
^

If I do the same thing, but inside some function in libtest.c

#include "libtest.h"

int foo()
{
    a = 10;
    return(0);
}

cc -c libtest.c

compiles without any warnings. What is the difference ?

3

There are 3 best solutions below

0
Clifford On BEST ANSWER

You cannot assign a variable outside a function, only define and initialise. Syntactically your a = 10; is a re-definition of a, which presumably subsequent errors make clear.

To provide static initialisation of a, in the header you should have;

extern int a ;

and then in the C source;

#include "libtest.h"

int a = 10 ;
0
Quimby On

You cannot assign to a variable from outside of functions. When would such code be called?

The compiler interprets this as a definition of a variable, from old days of C, missing type defaulted to int.

0
August Karlstrom On

You cannot put statements (in this case an assignment) outside of a function. Giving a variable a value in its declaration is called initialization. Moreover, when you declare a variable in a header file it should be declared extern and its definition should be put in the corresponding implementation file. It's also a good idea to prefix all exported variables and functions with a module name so that you know where they comes from. This also prevents name clashes.

Example:

M.h

#ifndef M_H
#define M_H

extern int M_a;

#endif

M.c

#include "M.h"

int M_a;

main.c

#include "M.h"

int main(void)
{
   M_a = 10;
   return 0;
}

The ifndef-define macro is to avoid the header file from being included multiple times in the same translation unit.

Also, in general it's advisable not to export variables but instead export get and set functions which can guarantee the integrity of the variable. For instance, M_a may be a variable which should always be non-negative and in that case we can define the setter as

void M_SetA(int val)
{
   assert(val >= 0);
   M_a = val;
}