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 s 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:
Jan 01, 2024