C++ 编译器如何获得常量';s地址的C++;?
正如这里所讨论的,编译器在编译代码时可能不会为常量分配任何存储,它们可能直接嵌入到机器代码中。那么编译器如何获取常量的地址呢 C++代码:C++ 编译器如何获得常量';s地址的C++;?,c++,compilation,constants,C++,Compilation,Constants,正如这里所讨论的,编译器在编译代码时可能不会为常量分配任何存储,它们可能直接嵌入到机器代码中。那么编译器如何获取常量的地址呢 C++代码: void f() { const int a = 99; const int *p = &a; printf("constant's value: %d\n", *p); } 所有变量都必须是可寻址的。编译器可能会优化常量变量,但在您使用变量地址的情况下,它无法做到这一点。常量是否会被分配任何存储完全取决于编译器。编译器可以
void f()
{
const int a = 99;
const int *p = &a;
printf("constant's value: %d\n", *p);
}
所有变量都必须是可寻址的。编译器可能会优化常量变量,但在您使用变量地址的情况下,它无法做到这一点。常量是否会被分配任何存储完全取决于编译器。编译器可以根据规则执行优化,只要程序的可观察行为没有改变,编译器可以为
a
分配存储,也可以不分配存储。请注意,这些优化不是标准要求的,而是标准允许的
显然,,当您获取此
常量的地址时,编译器将必须返回一个地址,您可以通过该地址引用a
,因此它必须将a
放在内存中,或者至少假装它这样做。编译器可能会执行许多允许执行的技巧,直到它影响程序的可见行为为止(见附件)。因此,它可能不会为const objectconst int a=99分配存储代码>,但在您获取变量地址的情况下-必须为其分配一些存储,或者至少假装是,您将获得允许您引用a
的内存地址。
代码:
我们看到的是变量const int a=99
实际上是内置的机器代码,不驻留在内存的特定区域(堆栈、堆或分配给它的数据段上没有内存)。如果我错了请纠正我。我想你必须远离C++告诉编译器怎么做的想法。在这种情况下,C++的规则表示必须调用PrtTf,并且必须用99的值调用它。编译器如何到达那里取决于编译器。或者“当你获取这个const
的地址时,编译器必须出现以将其放入内存中。”如果结果仍然相同,指针当然可能有一个完全乱码的值。事实上,它可以完全摆脱指针,只需将*p
替换为99
@Nawaz我在评论中编辑了更多细节。它只需要提供一种错觉,即对象有一个可以取消引用的地址。@sftrabbit:这是真的。这肯定是一个实现细节。@Nawaz为什么这是正确的?当然,编译器可以将整个函数优化到printf(“常量的值:%d\n”,99)代码>?变量地址被使用了,但不是以一种可观察的方式。@JBentley:答案也谈到了编译器执行的优化,不是吗?告诉我答案到底出了什么问题?变量是不可寻址的还是什么?@Nawaz不,答案声称它“无法”优化掉常量变量,因为它的地址被取下了,但如果地址从未以可观察的方式使用,那么我不明白为什么这是真的。@JBentley:我想说你不明白答案。请重读一遍。或者也许Joachim会编辑答案来消除你的疑虑。@Nawaz我重新阅读了它,它似乎相当清楚:它声称“在哪里使用变量地址”(并声明OPs代码就是一个例子),那么编译器“不能……优化常量变量”。如果你认为解释应该不同,那么请解释。
#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;
}
.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