Const limits the usage of constants and does not describe how constants should be allocated. If the compiler knows all the usage of a const, it may not even allocate space for the const. The simplest common case is that the constant value is known during compilation and does not need to be stored.
Constant variable: const type specifier variable name
Regular reference: const type description & reference name
Common Object: Class Name const Object Name
Common member function: Class Name: fun (parameter) const
Regular array: type description const array name [size]
Regular pointer: const type specifier * pointer name, type specifier * const pointer name
First, you will be prompted: in the constant variables (const type specifier variable name), regular references (const type specifier & reference name), regular objects (Class Name const object name), regular array (type specifier const array name [size]), the positions of const and "type specifiers" or "class names" (in fact, class names are custom type specifiers) can be exchanged.
Today, my colleague asked a question about the change of the const value. This question is frequently asked during the interview, so I wrote a blog summary.
The Code is as follows:
Output result: a: 10 p: 20
Simple analysis:
In fact, the reason for this problem is relatively simple. In the printf call, because a is a constant, the compiler has been optimized and the value of a is directly replaced with 10, therefore, when the memory location of a is changed to 20 in the future, it does not affect the parameter of printf. Of course, my colleagues did not trust my analysis. I can only call the compiled code for analysis.
Deep analysis:
1. Generate assembly code:
G ++-S test. cpp # The output assembly code is located in test. s.
2. The Assembly Code is as follows:
According to row 3, I verified the above analysis. At this time, my colleagues wanted me to explain the logic of the entire Assembly Code (I was overjoyed that I just attended the @ Lin shding course recently, by the way)
3. function call knowledge
To understand the function call stack, several concepts need to be clarified in advance:
A. the way stack grows is from high to low (university textbooks will be backed up long ago, but they must be truly understood)
B. parameter transfer method: Register + Stack
C. % rsp: Stack header pointer. push pop changes the corresponding pointer value.
D. % rbp: frame pointer. This concept is very important. The starting position of the current function stack,
Use % rbp + offset to access local variables and transmit parameters. The following figure shows a figure in @ Lin shding's courseware.
4. Assembly analysis:
Main:
. LFB2:
Pushq % rbp # Save the original frame pointer
. LCFI0:
Movq % rsp, % rbp # Save the current % rsp to % rbp, current frame
. LCFI1:
Subq $32, % rsp # Move the stack down to 32 Bytes, which saves the main parameter and the local variable in the main.
. LCFI2:
Movl % edi,-4 (% rbp) # obtain the argc Value
Movq % rsi,-16 (% rbp) # obtain the argv value. Why does it occupy 12 bytes? Subsequent analysis
Movl $10,-20 (% rbp) # assign 10 to
Leaq-20 (% rbp), % rax # Get the address of a to % rax
Movq % rax,-32 (% rbp) # assign the address of a to p (int *). The offset of 32 is to be analyzed.
Movq-32 (% rbp), % rax # Remove p value to % rax
Movl $20, (% rax) # assign a value to * p
Movq-32 (% rbp), % rax
Movl (% rax), % edx # The two steps are equivalent to * p, and assign the value to the register as the printf parameter.
Movl $10, % esi # pass the 10 parameter (actually)
Movl $. LC0, % edi # "a: % d p: % dn"
Movl $0, % eax # this function will be analyzed later
Call printf
Movl $0, % eax # Return Value of main Function
Leave
Ret
5. Analysis of other problems:
A. Why is there an exception in the stack location offset between argv and p? The main reason is that the size of argc and a is 4 Bytes, and the system is 64 Bits, so 8 Bytes alignment exists,
Here we can verify that a variable B is declared separately after a, and the space on the stack is just the gap
B. movl $0, % eax: When passing parameters of variable parameters, % eax indicates the number of using vector register (float type parameters can be passed to printf for verification)