declaration and definition

First, definition of "delcaration":

C99 6.7

"A declaration shall declare at least a declarator (other than the parameters of a function or the members of a structure or union), a tag, or the members of an enumeration."

now the difference between declaration and definition directly from C99:

C99 6.7

"A declaration specifies the interpretation and attributes of a set of identifiers. A definition of an identifier is a declaration for that identifier that:

— for an object, causes storage to be reserved for that object;

— for a function, includes the function body;

— for an enumeration constant or typedef name, is the (only) declaration of the identifier."

In short, a declaration only makes a statement on "an identifier" in terms of its name, type, linkage, scope, storage duration, without storage information. Compile does not need to allocate any storage inside the final binary file for a declaration. However, for a definition, compiler will need to immediately allocate storage, hence the final binary file size "may" increase. ( why may? see later food for thoughts )

In one line summary: definition = declaration + storage information.

a few quick example on declaration:

typedef int my_int; // a pure declaration, no definition information.

extern int *a; // a pure declaration with scope of the identifier specified. no storage allocated when compile it

extern int a[]; // ditto

static int a; // ditto

struct _a { // pure declaration, no storage allocated.

int a;

} a;

int my_function( int, int ); // pure declaration, no storage allocated.

since a definition is automatically a declaration, I will skip examples here.

Why we need declaration, why not just definition?

well, "extern int " and "typedef" example above already give the answer: facilitate compiler to compile a piece of source code

Note it is "compile" only. When we need to link all the compiled source code into one executable, which is called "linking", we need the definition. Some source code some where has to define the storage of the identifier.

relationship to imcomplete type

the definition of "incomplete type" is:

C99 6.2.5

"types that describe objects but lack information needed to determine their sizes"

since definition will always define the storage, incomplet type can only appear in a declaration.

E.g.,

extern int a[]; // we know a is an array, the array is stored somewhere, but not sure about its size.

typedef struct a a_t; // we only declared an identifier "a_t" which is an alias of structure of type "a", but no storage information yet.

void *a; // "void" is an incomplete type, however, this is a definition, it has the same storage of a "char pointer"

food for thoughts

if I define a global variable "int a[100]", and later change it to "int a[100000]". Those are clearly definitions that define the storage, will the second definition cause the final binary object file size blow up? :-)