正如这里所讨论的,C++ 中哪个内存区域是 const 对象?,编译器在编译代码时可能不会为常量分配任何存储空间,它们可能会直接嵌入到机器代码中。那么编译器如何获得常量的地址呢?
C++ 代码:
void f()
{
const int a = 99;
const int *p = &a;
printf("constant's value: %d\n", *p);
}
正如这里所讨论的,C++ 中哪个内存区域是 const 对象?,编译器在编译代码时可能不会为常量分配任何存储空间,它们可能会直接嵌入到机器代码中。那么编译器如何获得常量的地址呢?
C++ 代码:
void f()
{
const int a = 99;
const int *p = &a;
printf("constant's value: %d\n", *p);
}
是否为常量分配任何存储空间完全取决于编译器。允许编译器根据As-If规则执行优化,只要程序的可观察行为不改变编译器可能会分配存储空间,a
也可能不会。请注意,这些优化不是必需的,而是标准允许的。
显然,当您获取此地址时const
,编译器必须返回一个您可以引用的地址,a
因此它必须放置a
在内存中或至少假装它这样做。
所有变量都必须是可寻址的。编译器可能会优化常量变量,但在您使用变量地址的情况下,它无法做到这一点。
编译器可能会做许多允许它做的技巧,直到它会影响程序的可见行为(参见as-if rule)。因此它可能不会为 const 对象分配存储空间const int a = 99;
,但是在您获取变量地址的情况下 - 它必须分配一些存储空间或至少假装是,您将获得允许您引用的内存地址a
。代码:
#include <cstdlib>
using namespace std;
#include <cstdio>
const int a = 98;
void f()
{
const int a = 99;
const int *p = &a;
printf("constant's value: %d\n", *p);
}
int main(int argc, char** argv)
{
int b=100;
f();
return 0;
}
gcc -S main.cpp:
.file "main.cpp"
.section .rodata
.LC0:
.string "constant's value: %d\n"
.text
.globl _Z1fv
.type _Z1fv, @function
_Z1fv:
.LFB4:
.cfi_startproc
.cfi_personality 0x3,__gxx_personality_v0
pushq %rbp
.cfi_def_cfa_offset 16
movq %rsp, %rbp
.cfi_offset 6, -16
.cfi_def_cfa_register 6
subq $16, %rsp
movl $99, -4(%rbp)
leaq -4(%rbp), %rax
movq %rax, -16(%rbp)
movq -16(%rbp), %rax
movl (%rax), %eax
movl %eax, %esi
movl $.LC0, %edi
movl $0, %eax
call printf
leave
ret
.cfi_endproc
.LFE4:
.size _Z1fv, .-_Z1fv
.globl main
.type main, @function
main:
.LFB5:
.cfi_startproc
.cfi_personality 0x3,__gxx_personality_v0
pushq %rbp
.cfi_def_cfa_offset 16
movq %rsp, %rbp
.cfi_offset 6, -16
.cfi_def_cfa_register 6
subq $32, %rsp
movl %edi, -20(%rbp)
movq %rsi, -32(%rbp)
movl $100, -4(%rbp)
call _Z1fv
movl $0, %eax
leave
ret
.cfi_endproc
.LFE5:
.size main, .-main
.section .rodata
.align 4
.type _ZL1a, @object
.size _ZL1a, 4
_ZL1a:
.long 98
.ident "GCC: (Ubuntu/Linaro 4.4.7-2ubuntu1) 4.4.7"
.section .note.GNU-stack,"",@progbits
所以我们看到的是这个变量const int a = 99;
实际上是内置在机器代码中的,并不驻留在特定的内存区域(堆栈、堆或分配给它的数据段上没有内存)。如果我错了,请纠正我。