Preface:
Looking at the memory management of cpp today, I happen to think which memory area is the variable modified by the keyword const? Then I made a search on the Internet and communicated with Dashen in the group, and reached the following conclusions.
Conclusion:
1. Const modification is not a constant, but a read-only quantity. Replace all the values assigned to the const variable at compile time (which is similar to the macro in C language). At run time, the const variable can be modified in memory:
1.1) The const variable located on the stack can be modified by memory (pointer). The grammar is in accordance with the rules, and the compilation run will not error. However, at compilation time, all the places where the constant is used are replaced by the value given by the definition, and then the value modified by pointer can not be used when running.
1.2) Modify the const variable in the static storage area by memory (pointer). There are no grammatical errors, compilation will not make errors, and once run, an exception will be reported.
Note: By modifying const variables on the global area through pointers, compilation can pass, and operation will report an exception.
Const guarantees the invariance of constants used only during compilation, and cannot guarantee the behavior during operation. Programmers modifying constants directly will get a compilation error, but using indirect pointers to modify memory will not get any errors and warnings as long as it complies with the grammar. Because the compiler can't know whether you intentionally or unintentionally changed it, but since it's defined as const, programmers should not modify it, otherwise they can define it directly with variables.
The test code is as follows:
const int a = 1; void test1() { const int c = 3; int* p = (int*)& c; *p = 4; //c was replaced by 3 at compilation time, and the modified value through memory could not be used. //* p represents the modified value of c cout << c << " " << *p << endl; p = (int*)& a; //When compiled, a is replaced by 1, and p points to the address of a. cout << a << " " << *p << endl; //Modify const variables located in static storage, compile correctly, and run will report exceptions *p = 4; //The value of a is still 1, because at compilation time the letter A is replaced by 1 and an exception is reported at run time. cout << a << endl; }
2. Const volatile-modified variables can be compiled without replacing all the values assigned by const volatile variables at compile time. Therefore, the values modified by memory can be used at run time:
2.1) The const volatile variable located in the stack area can be modified by memory (pointer). The grammar is in accordance with the rules. Compilation runs without error. At compilation time, all places where the constant is used will not replace the value given by the definition. At run time, the value modified by pointer can be used.
2.2) Modify the const volatile variable in the static storage area by memory (pointer). There are no grammatical errors, no compilation errors, and an exception will be reported once it runs.
Note: By modifying const variables on the global area through pointers, compilation can pass, and operation will report an exception.
The test code is as follows:
void test2() { const volatile int c = 3; //const volatile modifies variables that only use the values they are given at initialization when they are running //const volatile-modified variables are not replaced at compilation time cout << c << endl; void* p = (void*)&c; (*(int*)p) = 4; //Modify the value of c to 4 cout << c << endl; p = (void*)& b; //When modifying const volatile variables in static storage at runtime, compilation errors and running errors occur. (*(int*)p) = 5; cout << b << endl; }
3. const-modified variables are located in the stack or static storage, not in the symbol table (constant table):
The test code is as follows:
const int i = 100; int n = 0; class CTest { public: CTest() :j(0), l(0) {}; int l; const int j; static const int k = 102; }; void test3() { CTest ct; int m = 0; const int o = 0; long addri = (long)& i; long addrl = (long)& ct.l; long addrj = (long)& ct.j; long addrk = (long)& ct.k; long addrm = (long)& m; long addrn = (long)& n; long addro = (long)& o; cout << "addr i=" << addri << endl; //addr i = 2989028 (symbol table) cout << "addr l=" << addrl << endl; //addr l = 15989288 cout << "addr j=" << addrj << endl; //addr j = 15989292 cout << "addr k=" << addrk << endl; //addr k = 2988856 (symbol table) cout << "addr m=" << addrm << endl; //addr m = 15989276 cout << "addr n=" << addrn << endl; //addr n = 29985882 (symbol table) cout << "addr o=" << addro << endl; //addr o = 15989264 }