I am new to C and I experience some confusion between the declaration and definition of a variable. Another thing I would like to know is if the following is true:
"Declaration appears many times and definition comes once."
Also:
int x;
Is this a declaration only? Since memory is allocated for x
then why isn't this a definition instead of a declaration?
Simply writing int x;
at either global scope or local scope, is both a declaration and definition. Typically, the declaration tells the compiler "This variable will exist, at some point, under this name, so you can use it." The definition tells the compiler to actually arrange for the variable to be created - obviously this can only happen once.
Typically the way you'll use this is by putting in a header file:
// Foo.h
#ifndef FOO_H
#define FOO_H // make sure structs aren't redefined
extern int bar; // Declare a variable bar
#endif
And in a single source file
#include "foo.h"
int bar; // Define bar
If you were to define bar in multiple files, you would get an error; you can't create the variable twice. But you do have to tell the compiler about it in every source file you use bar
in. Hence the extern
declaration.
The precise semantics are defined in §6.9.2 of the C standard and can be summarized as follows:
static
storage-class specifier, it is a tentative definition. If the translation unit (file) has one or more tentative definitions and no external definition, the compiler automatically adds a true file scope declaration at the end of the translation unit, with a zero initializer. (§6.9.2/2)What this means is that, strictly speaking, int x;
is not a definition; but it automatically creates a definition if and only if there is no other definition with an initializer, and no static
definition (this third case is undefined behavior due to linkage disagreement per §6.2.2/7)
Note that extern int x;
is not an external definition. It is a declaration with an extern
storage class specifier. As such, extern int x;
alone does not cause a definition to be created, but if you have both:
extern int x;
int x;
Then you will end up having a definition created at some point in the file.
It is also, technically speaking, legal to do this:
extern int x;
int x;
int x = 42;
In this case, the int x;
in the middle is superfluous and has no effect. That said, this is poor form, as it's confusing in this case where the actual definition is.
This isn't something you see too much in C, but it works like this:
In a header file, you can have a line like this:
extern int x; //declaration
Because of the extern
modifier, this tells the compiler that there is an int named x somewhere. The compiler doesn't allocate space for it - it just adds int x
to the list of variables you can use. It'll only allocate space for x
when it sees a line like this:
int x; //definition
You can see that because only the int x;
line changes your executable, you can have as many extern int x;
lines as you feel like. As long as there's only int x;
line, everything will work like you want it to - having multiple declarations doesn't change a thing.
A better example comes from C++ (sorry if this is a C-only question - this applies to struct
s as well, but I don't know the syntax off the top of my head):
class Pineapple; //declaration
Pineapple* ptr; //this works
Pineapple pine; //this DOES NOT work
This declaration tells the compiler that there's a class called "Pineapple". It doesn't tell us anything about the class (how big it is, what its members are). We can use pointers to Pineapples now, but we can't yet have instances - we don't know what makes up a Pineapple, so we don't know how much space an instance takes up.
class Pineapple
{
public:
int ounces;
char* name;
}; //definition
Pineapple* ptr; //still works
Pineapple pine; //this works now too!
//we can even get at member variables, 'cause we know what they are now:
pine.ounces = 17;
After a definition, we know everything about the class, so we can have instances, too. And like the C example, you can have multiple declarations, but only one definition.
Hope this helps!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With