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