Home | Projects | Notes > C Programming > const
Type Qualifier
const
Type Qualifier
const
Type Qualifierconst
is a type qualifier in C used to enforce read-only feature on variables. It adds some safety to your code. The compiler will warn you when you try to modify the value of the const
variable.
xxxxxxxxxx
21uint8_t data1 = 10; /* data1 is called a variable */
2data1 = 50; /* OK; data1's value can be modified throughout the program */
xxxxxxxxxx
21const uint8_t data2 = 10; /* data2 is called a constant (read-only) variable */
2data2 = 50; /* compile-time error; data2's value cannot be modified */
Use const
generously to enforce pointer access restrictions while writing functions and function prototypes.
Using const
may also help the compiler generate the optimized code.
const
Type Qualifier?Syntax:
xxxxxxxxxx
21const uint8_t data1 = 10;
2uint8_t const data1 = 10; /* data1 is a constant (read-only) variable of type uint8_t */
Some programmers prefer the second way because it helps interpret a complex statement better (i.e., Reading backwards). First, identify the variable name, then read from left to right.
const
ness of a VariableBy using the const
keyword, you (as a programmer) are just making a promise to the compiler that you won't try to modify the content of the variable using its name.
If you try to modify the variable by its name, the compiler will stop you by throwing an error (i.e., compile-time error).
xxxxxxxxxx
21const uint8_tdata = 10;
2data = 50; /* compile-time error */
However, you can still modify the content of the variable by using a pointer of an appropriate type that points to that variable.
xxxxxxxxxx
31const uint8_t data = 10;
2uint8_t *ptr = (uint8_t*)&data; /* ptr does not know anything about the constness of data */
3*ptr = 50; /* OK */
const
does NOT mean that the value will never change. It is just a programming safety feature to prevent the programmer from modifying the value in a certain way.
const
Variables in MemoryAll local const
variables are just like non-const
variables as far as memory placement is concerned. They are placed in RAM. The only specialty of a const
variable is that it is read-only.
All global const
variables are stored in ROM or FLASH. This also further depends on the linker script rules and the hardware on which the code runs.
For example, in STM32 target hardware, all global const
variables reside in the FLASH memory. So, when you try to modify the const
variable using its address, the operation will have no effect because the FLASH memory of the microcontroller is write-protected.
xxxxxxxxxx
91 const uint8_t data = 10; /* global const variable (stored in ROM or FLASH) */
2
3int main(int argc, char *argv[])
4{
5 uint8_t *ptr = (uint8_t*)&data;
6 *ptr = 50; /* run-time error (e.g., segmentation fault)
7 programmers are not allowed to change the data stored in the read-only memory
8 section by using a pointer in the code */
9}
const
Type QualifierSyntax:
xxxxxxxxxx
31const uint8_t data = 50; /* data is read-only */
2
3data = 10; /* not allowed */
Use case:
To define mathematical constants in the program
xxxxxxxxxx
31const float pi = 3.14;
2const float fadius = 4;
3const int number_of_months = 12;
Syntax:
xxxxxxxxxx
41const uint8_t *pData = (uint8_t*)0x40000000; /* pData is a pointer to a read-only data */
2
3pData = (uint8_t*)0x50000000; /* allowed */
4*pData = 50; /* not allowed */
Here, the pointer pData
is modifiable, but from pData
's perspective the memory location it points to is not modifiable (read-only). Note that this does not necessarily mean that the memory location itself is non-modifiable in nature. It's just that pData
recognizes it that way because of the way pData
is declared.
Use case:
In the following function, src
is guarded to prevent the data pointed to by src
from being modified by mistake.
xxxxxxxxxx
81/* copies data from src to dst */
2void copy_src_to_dst(const uint8_t *src, uint8_t *dst, uint32_t len)
3{
4 for (uint32_t i = 0; i < len; i++)
5 {
6 *dst++ = *src++;
7 }
8}
This usage can be found in many system call declarations:
xxxxxxxxxx
21int open(const char *path, int oflag, ...);
2ssize_t write(int fd, const void *buf, size_t count);
Syntax:
xxxxxxxxxx
41uint8_t *const pData = (uint8_t*)0x40000000; /* pData is a constant pointer to a modifiable data */
2
3pData = (uint8_t*)0x50000000; /* not allowed */
4*pData = 50; /* allowed */
Here, the pointer pData
is not modifiable (read-only), but from pData
's perspective the memory location it points to is modifiable.
Use case:
Use to improve readability and guard the pointer variables.
xxxxxxxxxx
91/* updates the details of age and salary into the pointer provided by the caller */
2void update_user_data(uint8_t *const pUserAge, uint32_t *const pUserSalary)
3{
4 if (pUserAge != NULL)
5 *pUserAge = getUserAge();
6
7 if (pUserSalary != NULL)
8 *pUserSalary = getUserSalary();
9}
Syntax:
xxxxxxxxxx
41const uint8_t *const pData = (uint8_t*)0x40000000; /* pData is a constant pointer to a constant data */
2
3pData = (uint8_t*)0x50000000; /* not allowed */
4*pData = 50; /* not allowed */
Here, the pointer pData
is not modifiable (read-only), and from pData
's perspective the memory location it points to is also not modifiable (read-only).
Use case:
Use when reading data from the status register of the hardware. Contents of the status register shouldn't be modified by the programmer.
xxxxxxxxxx
61/* reads and returns the content of the status register pointed to by pStatusReg
2 (accidental write to the status register may cause unpredictable consequences) */
3uint32_t read_status_register(const uint32_t *const pStatusReg)
4{
5 return (*pStatusReg);
6}
The first const
keyword can be on either side of the type:
xxxxxxxxxx
21const int *ptr; /* int const *ptr; */
2const int *const ptr; /* int const * const ptr; */
More examples on const
usage:
xxxxxxxxxx
51int **ptr; /* pointer to a pointer to an int */
2int ** const ptr; /* const pointer to a pointer to an int */
3int * const *ptr; /* pointer to a const pointer to an int */
4const int **ptr; /* pointer to a pointer to a const int */
5int * const * const ptr; /* const pointer to a const pointer to an int */