Const keyword in Dynamic C

For a more complete summary, please reference section 4.4 of the DC User’s Manual
This is a summary of the information found in section 4.4 of the DC User’s Manual

Simple constants

The const keyword allows a programmer to tell the compiler that a particular variable should not be modified after the initial assignment in its declaration. If any code tries to assign a new value to that variable, the compiler will generate an error “Assignment to read-only variable not allowed” indicating that the assignment operation should not occur. This allows a programmer to prevent unwanted modifications to variables that for some reason should not be changed. Note that const variables must be initialized; otherwise there is no other way to assign them values.

The following is an example of a simple declaration of a constant integer:

const int number = 42;

Note that the const in the above declaration can also come after the type, as in the following:

int const number = 42;

In a simple const variable declaration, any storage type may be used. It is possible to have an auto const variable; it simply means that the value is stored on the stack and cannot be modified. In most cases, simple const declarations should probably be static (this is not the case with pointers, as we will see below). Constants are non?modifiable so multiple accesses (say via a re?entrant function) will all be reads, thus making a single storage location preferable to allocating space for the constant on the stack for each call. The implication is that a local const should preferably be declared static (as opposed to auto), as in:

 

void foo(void)

{

// the following uses a single shared storage location for each call to foo

static const int foo_local_static = 1;

// the following uses a unique, non-shared stack storage location for each call to foo

// (which storage space will add up if foo is called in a reentrant manner, e.g. recursively)

auto const int foo_local_auto = 1;

. . .

}

Const and pointers 

Simple variable declarations with const are straightforward and fairly easy to understand. However, const is much more interesting when applied to pointers. The rules are fairly simple, but the resulting behavior can be somewhat confusing.

To begin, let’s look at the declaration for a simple pointer, in this case a string literal constant:

const char * string = “ABCD”;

Here we see a const modifier on a pointer declaration. As in the simple declaration in the previous section, the declaration starts with const.

However, since this is a pointer, the meaning may be slightly confusing. The const in this case actually refers to the character being pointed at (the ‘A’ in the string literal “ABCD”) and not the variable string. The reason for this is that string is actually a pointer to a constant character, in this case our literal value. The pointer string is actually a variable that can be modified, but dereferencing string and assigning to it will result in an error:

string = another_string; // This is OK

*string = ’X’; // ERROR Assignment to read-only variable not allowed

Now, it is possible to make string into a constant, and C provides a somewhat unintuitive syntax, as follows:

char * const const_string = another_string;

In this declaration, note that the const modifier comes after the "*" defining string to be a pointer. In this case, const_string itself is constant and cannot be modified, but what it points to can be, as in the following:

const_string = yet_another_string; // ERROR Assignment to read-only variable not allowed

*const_string = 'X'; // This is OK

Furthermore, it is possible to declare both the pointer and what it points to as constant, with the resulting behavior:

const char * const really_const_string = "ABCD"; // Declaration

really_const_string = yet_another_string; // ERROR Assignment to read-only variable not allowed

*really_const_string = 'X'; // ERROR Assignment to read-only variable not allowed

 Differences between Dynamic C versions 

The following table demonstrates some examples of const behavior prior to the ANSI?compliant const behavior in Dynamic C 10.64, and compares the old non?ANSI behavior with the new to give you an idea on how to port code from older versions of Dynamic C. Note that non?const initializers were added in Dynamic C 10.60 so there will be some subtle differences porting from that version as compared to porting from earlier versions.

 Note that const is used to explicitly define that the storage of the associated value is to be in flash. On later devices that store the program in flash but run in RAM, the const values were stored with the code in RAM following the startup flash?to?RAM copy. With const correctness, the storage is defined by the storage class (auto or static) and literals are stored in flash (or with the code for run?in?RAM devices).

Const examples 

Const Example

Older Dynamic Behavior

Behavior in DC 10.64 and Later

const int x = 10;

x is stored in flash

x is stored in the default storage class (auto in functions, otherwise extern) and is nonmodifiable (const). The value x may be stored in flash.

auto const x = 10;

Error, auto const not allowed

x is stored on the stack but is not modifiable

const char* S = “ABCD”;

“ABCD” and S are both const and stored in flash. Prior to version 10.60, a second const (for the pointer) was required and this code would have produced a warning.

“ABCD” is stored in flash/constant space, but S is stored using the default storage class and is modifiable (nonconst)

const char * const S = “ABCD”

Same as ‘const char* S = “ABCD”’

“ABCD” and S are both const and stored in flash/constant space

char * const ptr = &s;

Error – some older versions would ask for const before the “char”. More recently this would compile without error.

The variable ptr is a non-modifiable (const) pointer stored in flash/constant space to a modifiable character in RAM

int foo(const int x);

Error – const not allowed for function parameters

The parameter x is stored on the stack but is not modifiable within the function foo

int foo(char * str) { }

const char * const s = “ABCD”;

foo(s);

OK, const property of variable s is ignored in function call

Warning at function call – passing to foo discards the const modifier of s

Variable initializers were introduced in Dynamic C 10.60, which changed some of the behavior for initialized variables. Other const changes are new with Dynamic C 10.64. The table primarily refers to the behavior prior to version 10.60.



Last updated: Jun 11, 2019

Filed Under

Embedded

Recently Viewed

No recently viewed articles

Did you find this article helpful?