6

正如这里所讨论的,C++ 中哪个内存区域是 const 对象?,编译器在编译代码时可能不会为常量分配任何存储空间,它们可能会直接嵌入到机器代码中。那么编译器如何获得常量的地址呢?

C++ 代码:

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

3 回答 3

11

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

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

于 2013-04-07T13:17:49.047 回答
2

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

于 2013-04-07T13:17:40.953 回答
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;实际上是内置在机器代码中的,并不驻留在特定的内存区域(堆栈、堆或分配给它的数据段上没有内存)。如果我错了,请纠正我。

于 2013-04-07T13:37:07.783 回答