C++ 编译器如何获得常量';s地址的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); } 所有变量都必须是可寻址的。编译器可能会优化常量变量,但在您使用变量地址的情况下,它无法做到这一点。常量是否会被分配任何存储完全取决于编译器。编译器可以

正如这里所讨论的,编译器在编译代码时可能不会为常量分配任何存储,它们可能直接嵌入到机器代码中。那么编译器如何获取常量的地址呢

C++代码:

void f()
{
    const int a = 99;
    const int *p = &a;
    printf("constant's value: %d\n", *p);
}

所有变量都必须是可寻址的。编译器可能会优化常量变量,但在您使用变量地址的情况下,它无法做到这一点。

常量是否会被分配任何存储完全取决于编译器。编译器可以根据规则执行优化,只要程序的可观察行为没有改变,编译器可以为
a
分配存储,也可以不分配存储。请注意,这些优化不是标准要求的,而是标准允许的


显然,,当您获取此
常量的地址时,编译器将必须返回一个地址,您可以通过该地址引用
a
,因此它必须将
a
放在内存中,或者至少假装它这样做。

编译器可能会执行许多允许执行的技巧,直到它影响程序的可见行为为止(见附件)。因此,它可能不会为const object
const 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