Declaration and Definition
In simple terms, the main difference between declaration and definition is that declaration mentions the type and structure of a variable or a function. Whereas definition allocates memory for a variable or function.
int add(int a, int b);
is a function prototype and is a function declaration. This line has not allocated any storage for the function in the code segment of the program.
int add(int a, int b)
is a function definition for which storage is allocated in the code segment of the program.
Similarly it is possible to declare or define variables.
int a = 10;
Now in this case, both the above statements are definitions, the only difference being that a is initialized with value 10 whereas b has no initial value. It means both have storage allocated in the data segment of the program. However if you want to specify a variable declaration without allocating memory on the data segment, you have to prefix the extern keyword.
extern int c;
extern int d = 10;
If the variable is prefixed with extern and has no initializer, it is a variable declaration. However explicitly initializing the external variable with a value becomes a definition, which means storage is allocated for it. Hence in the above statements, c is a declaration and d is a definition with storage allocated.
Now comparing the function and variable declaration, you might be wondering why there is no extern prefix for a function declaration. The fact is that extern keyword is automatically pre-appended to a function declaration even if the user doesn’t specify it.
int add(int a, int b);
extern int add(int a, int b);
Hence the add declaration written by the programmer is automatically upgraded to a declaration with extern prefix by the compiler.
Now coming to the scope of variables and functions, the following always holds:
- Function and variable declarations have external linkage, i.e. they are visible outside the file they are declared in. (They have ‘extern’ prefix, remember)
- Function and variable definition have internal linkage, i.e. they are visible only in the file they are defined.
The const keyword in C/C++ specifies whether the variable/object can be changed or not. If it’s a const in a function, it just means that the variable or object may not be changed. The const keyword mentioned after a function definition or declaration takes it a step further. It means that the function may not modify any variable or object in its definition.
However in C++, const_cast casting can be used to cast away the const’ness of the variable and allow it to be changed. This however means that the programmer is surely knowing what he/she is doing with the variable.
If however the programmer is sure that the variable might be changed in a const function, it may be mentioned as mutable. It simply means that the variable or object may be changed in a const function.
Constant folding is a concept in C++ where the value of a const variable is directly entered in the symbol table during compilation and the variable is not used. This is a compiler optimization only in C++. Do note that storage is compulsorily allocated for const in C.
So what about the scope of const variables? The following statements hold in this case:
- In C++, const variables have internal linkage, mainly because they are folded and no storage is allocated for them in the data segment.
- In C++, const variables which have a declaration using extern, have external linkage, because usage of extern keyword makes it visible outside the program file, hence storage is allocated in the code segment.
- In C, const variables always have storage allocated in the code segment and have external linkage.
Now when a novice programmer is asked the question, what is the use of a static variable, the reply usually is “It is used when the value of the variable has to persist across function calls”
Now when a variable is defined in a function, it is stored in the stack of the function call. So how does a variable value persist if the function is called repeatedly? Shouldn’t the function stack be pushed and unwound based on each function call? The answer here is that static variables or functions are never part of a function stack. They are stored in the global variables area of the program and this is how the value persists, this is how they can be accessed directly without a class object. The only difference is that when a variable in a function is static, its location is that of global variables, but its scope is confined only to the block where it is defined.
Hence the lifetime of static variables or functions is the lifetime of the file it is present in. It also means, destructors of static objects are called when the program ends and not when the function in which it is defined exits!
Reference: Thinking in C++ – Bruce Eckel