const qualifier in C
const
is the abbreviation for "constant". Unfortunately, because of this, many people think that the value qualified by const
is a constant. This is not correct. More accurately, it should be a read-only variable whose value cannot be used at compile time because the compiler does not know its stored content at compile time. Perhaps this keyword should have been replaced by readonly. So what is the use and meaning of this keyword?
The original purpose of const
was to replace precompiled instructions, eliminating their shortcomings and inheriting their advantages. Let's see the difference between it and the #define
macro.
In C, the const
keyword should probably be replaced with readonly.
qualify read-only var for immutability#
General variables are read-only variables of simple types. When defining such read-only variables, the const
qualifier can be used before or after the type specifier. For example:
int const i = 2;
or const int i = 2;
To define or declare a read-only array, you can use the following format:
int const a[5] = {1, 2, 3, 4, 5};
or const int a[5] = {1, 2, 3, 4, 5}
Look at the following example and think about it: is this way of writing correct?
Please create a const.c
file and a const.cpp
file and test them.
You will notice that gcc
will give an error when compiling the const.c
file, while g++
will compile the const.cpp
file just fine. Why is this?
gcc pointer-demo.c
reports error: variable-sized object may not be initialized.
We know that when defining an array, the number of elements must be specified. This also indirectly proves that in the C language, Max qualified by const
is still a variable, but it is only a read-only attribute; in C++, the meaning of const is extended, which will not be discussed here due to space limitations.
Note: const-qualified read-only variables must be initialized at the same time as they are defined. Think about why?
One question remains: Can a case
statement be followed by a const-qualified read-only variable? Please test it yourself.
avoid unnecessary allocation#
The compiler usually does not allocate memory for ordinary const
read-only variables, but stores them in the symbol table, which makes them a compile-time value without storage and memory read operations, making them very efficient. For example:
#define M 3 // macro
const int N = 5; // At this time, N is not put into memory
//...
int i = N; // Allocate memory for N at this time, and no more again
int I = M; // Macro replacement and memory allocation during precompilation
int j = N; // No more memory allocation
int J = M; // Perform macro replacement and allocate memory again
From an assembler point of view, the read-only variable defined by const
only returns the corresponding memory address, rather than an immediate value like #define
. Therefore, the read-only variable defined by const
has only one backup during program execution (because it is a global read-only variable stored in the static area), while the macro constant defined by #define
has several backups in memory. The #define
macro is replaced in the pre-compile stage, while the read-only variable qualified by const
has its value determined at compile time. The #define
macro has no type, while the read-only variable qualified by const
has a specific type.
qualify pointer and target#
const int *p; // p is mutable, the object pointed to by p is immutable
int const *p; // p is mutable, the object pointed to by p is immutable
int* const p; // p is immutable, the object pointed to by p is mutable
const int * const p; // both p and the object it points to are immutable
Here is a method to remember and understand: ignore the type name first (the compiler also ignores the type name when parsing), and see which one const
is closest to. "Whoever is close to the water gets the moon first", so it qualifies whatever it is close to.
- const
int*p; : const qualifies*p
, the objectp
points to is immutable intconst *p; : const qualifies*p
, dittoint* const p; : const qualifiesp
,p
is immutable- const
int* const p; : the first qualifies*p
, the latterp
, both immutable
Summary: The const
to the right of the asterisk qualifies the pointer variable, and the const to the left of the asterisk qualifies the location to which the pointer is pointing.
In a certain project, it is required to set the value of an integer variable with an absolute address of 0x67a9 to 0xaa66.
Normal operation:
A more obscure way:
implicit this pointer in C++#
Let's see how this
pointer works in C++ class. this
pointer is used implicitly in member functions, and the compiler automatically implements this
pointer. The implementation principle is to add an extra parameter to the member function, which is the this
pointer. Then, if the member function uses data members, the this
pointer is added implicitly. When calling a member function, the compiler automatically adds an extra actual parameter to the called member function, which is the address of the object that calls this function.
For example:
The compiler will automatically convert the member function to:
Its call will be automatically converted to ma.f(&ma);
.
Let's take a look at what the difference is within the constant member function.
The const
after the (empty) argument list in the function declarations indicates that these functions do not modify the state of a Class. Naturally, the compiler will catch accidental attempts to violate this promise.
The underlying mechanism is as follows: In a C++ constant member function, a hidden this
pointer is required when calling a member of a class. The this
pointer type of a const
member function is const CLASS_TYPE *const
, which means that neither the value of the this pointer itself nor the object it points to can be changed.
qualify function#
The const qualifier can also be used to qualify function parameters when you do not want the parameter value to be accidentally changed within the function body. For example:
It explicitly tells the compiler that *p
cannot be changed in the function body, thus preventing some unintentional or erroneous changes by the user.
Here are some typical function parameters qualified by const
in the standard library.
<string.h> - Null-terminated byte strings
size_t strlen( const char* str );
char *strcpy( char *dest, const char *src );
char *strstr( const char *str, const char *substr );
In addition, the const
qualifier can also be used to qualify the return value of a function, indicating that the return value cannot be changed. For example:
To reference a const
read-only variable in another linked file:
extern const int i; // right
extern const int j=10; // wrong, the read-only variable cannot be changed
Are we done with what we have covered so far? Far from it. In C++, const
has been extended, and there is still a lot of knowledge that has not been covered. If you are interested, you should look up the relevant information and study it.
The subject content of this article is referenced from the classic 《C语言深度解剖(第3版)》 | 第1章 关键字 - 1.13 const关键字也许该被替换为readonly
Sincere thanks to the original author!