Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C: Behaviour of the `const` keyword

I've been told that if I'm coding in ANSI C to declare in the order that the variables will be used, assert that pointers are not null and that indices are within bounds, and to initialize just before usage of the variable.

If I declare a const can I initialize it after a block of assertions and code?

In Java final initializations must occur at declaration, yet is it consistent through ANSI C implementations that I can initialize a const once, but not necessarily at the time of declaration?

like image 264
Ande Turner Avatar asked Sep 13 '09 10:09

Ande Turner


People also ask

Does C have the const keyword?

Yes, there's a const keyword in C. It's been there since C90. Syntactically, it can occur in the same places as in C++.

Why would you use const in C?

The const keyword allows you to specify whether or not a variable is modifiable. You can use const to prevent modifications to variables and const pointers and const references prevent changing the data pointed to (or referenced).

What is the keyword used for constant?

Constants are basically variables whose value can't change. In C/C++, the keyword const is used to declare these constant variables. In Java, you use the keyword final . However, the tool introduced here is not simply a primitive variable; it's an actual object instance.

Does const improve performance C?

const correctness can't improve performance because const_cast and mutable are in the language, and allow code to conformingly break the rules. This gets even worse in C++11, where your const data may e.g. be a pointer to a std::atomic , meaning the compiler has to respect changes made by other threads.


3 Answers

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;
}
like image 69
Pete Kirkham Avatar answered Sep 21 '22 02:09

Pete Kirkham


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
like image 33
2 revs, 2 users 83% Avatar answered Sep 23 '22 02:09

2 revs, 2 users 83%


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;
like image 42
Cat Plus Plus Avatar answered Sep 21 '22 02:09

Cat Plus Plus