正如此处Which memory area is a const object in in C++?所讨论的,编译器在编译代码时可能不会为常量分配任何存储,它们可能直接嵌入到机器代码中。然后编译器如何获得常量的地址?
C ++代码:
void f()
{
const int a = 99;
const int *p = &a;
printf("constant's value: %d\n", *p);
}
答案 0 :(得分:11)
是否将为任何存储分配常量完全取决于编译器。允许编译器按照 As-If 规则执行优化,只要程序的可观察行为没有改变,编译器就可以为a
分配存储空间,也可能不会。请注意,标准不允许这些优化,但允许这些优化。
显然,当您获取此const
的地址时,编译器必须返回一个地址,您可以通过该地址引用a
,因此必须将a
放入内存或至少假装它这样做。
答案 1 :(得分:2)
所有变量都必须是可寻址的。编译器可以优化常量变量,但在你使用变量地址的情况下,它不能这样做。
答案 2 :(得分:1)
编译器可能会执行许多技巧,这些技巧可能会影响程序的可见行为(请参阅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;
实际上是在机器代码中构建的,不驻留在特定的内存区域(堆栈上没有内存,堆或分配给它的数据段) )。如果我错了,请纠正我。