C: Behaviour of the `const` keyword
The Java compiler has a small amount of flow logic to allow you to initalise final
variables after their declaration. This is legal Java:
final int something;
if ( today == Friday )
something = 7;
else
something = 42;
Java will detect if any branches leave the final value undefined. It won't analyse the conditions, so this is not legal Java, even though it's logically similar:
final int something;
if ( today == Friday )
something = 7;
if ( today != Friday )
something = 42;
In ANSI C89, const
variables ( other than extern
) must be initialised in the statement they are declared in.
const int something = ( today == Friday ) ? 7 : 42;
The extern
modifier on a declaration tells the compiler that the variable is initialised in a different complation unit ( or elsewhere in this compilation unit ).
In ANSI C99, you can mix declarations and code, so you can declare and initialise a const
variable after a block of assertions and code. Portability of 1999 ANSI C remains an issue.
A work around for C89 is to note that the rules for declarations preceding code work at block scope rather than function scope, so you can do this:
#include<stdio.h>
int main ( void )
{
printf ( "wibble\n" );
{
const int x = 10;
printf ( "x = %d\n", x );
}
return 0;
}
const
variables are read-only and must be initialised where they're defined.
This code produces error: assignment of read-only variable 'foo'
(GCC 4):
const int foo;
foo = 4;
The same goes for const pointers (note here: const int *
is not a const pointer, but a pointer to const):
int * const foo;
foo = 4;
Be aware that even in C89, you can often move the definition closer to the point of first use by introducing a bare block just for the extra scope. Before:
int a, b, c;
a = 12;
// Do some stuff with a
b = 17;
// Do some stuff with a and b
c = 23;
// Do some stuff with a, b, and c
After:
int a = 12;
// Do some stuff with a
{
int b = 17
// Do some stuff with a and b
{
int c = 23;
// Do some stuff with a, b and c
}
}
With C99 of course, you can define variables other than at the beginning of a block:
int a = 12;
// Do some stuff with a
int b = 17
// Do some stuff with a and b
int c = 23;
// Do some stuff with a, b and c