6

As is discussed here Which memory area is a const object in in C++?, a compiler will probably not allocate any storage for the constants when compiling the code, they may probable be embedded directly into the machine code. Then how does a compiler get a constant's address?

C++ code:

void f()
{
    const int a = 99;
    const int *p = &a;
    printf("constant's value: %d\n", *p);
}
Community
  • 1
  • 1
imsrch
  • 1,152
  • 2
  • 11
  • 24
  • 4
    I think you've got to get away from the idea that C++ tells the compiler how to do something. In this case the rules of C++ says that printf must be called and that it must be called with a value of 99. How the compiler gets there is up to the compiler. – john Apr 07 '13 at 13:19

3 Answers3

11

Whether a constant will be allocated any storage or not is completely dependent on the compiler. Compilers are allowed to perform optimizations as per the As-If rule, as long as the observable behavior of the program doesn't change the compiler may allocate storage for a or may not. Note that these optimizations are not demanded but allowed by the standard.

Obviously, when you take the address of this const the compiler will have to return you a address by which you can refer a so it will have to place a in memory or atleast pretend it does so.

Community
  • 1
  • 1
Alok Save
  • 202,538
  • 53
  • 430
  • 533
  • Or "when you take the address of this `const` the compiler will have to *appear* to place it in memory." The pointer could of course have a completely gibberish value if the result is still the same. In fact, it could completely get rid of the pointer entirely and just replace `*p` with `99`. – Joseph Mansfield Apr 07 '13 at 13:20
  • @Nawaz I edited more details into my comment. It just needs to provide the illusion that the object has an address that you can dereference. – Joseph Mansfield Apr 07 '13 at 13:24
  • @sftrabbit: That is true. Its an implementation detail for sure. – Alok Save Apr 07 '13 at 13:27
2

All variables must be addressable. The compiler may optimize out constant variables, but in a case like your where you use the variable address it can't do it.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • @Nawaz Why is this correct? Surely the compiler can optimise the entire function down to `printf("constant's value: %d\n", 99);`? The variable address is used, but not in an *observable* way. – JBentley Apr 07 '13 at 13:46
  • @JBentley: The answer also talks about optimization performed by the compiler, doesn't it? Tell me what exactly is wrong with the answer? Variables are not addressable or what? – Nawaz Apr 07 '13 at 13:48
  • @Nawaz No, the answer claims that it "*can't*" optimize away the constant variable because it's address is taken, but if the address is never used in an observable way, then I don't see why that is true. – JBentley Apr 07 '13 at 13:49
  • @JBentley: I would say you didn't understand the answer. Please re-read it. Or maybe Joachim will edit the answer to clear your doubts. – Nawaz Apr 07 '13 at 13:50
  • @Nawaz I've re-read it, it seems fairly clear: it claims that "where you use the variable address" (and states that the OPs code is an example of this) then the compiler "can't .... optimize out constant variables". If you believe the interpretation should be different, then please explain. – JBentley Apr 07 '13 at 13:52
  • @JBentley: I read this answer as : 1) the variables are addressable. Period. 2) variables which are constant expressions can be optimized out, in which case they are not "addressable", which in turn contradicts point 1. Conversely speaking, if you take the address, then they must not be optimized out. DONE. Now it is a different matter altogether that *in the posted code* the whole program can be optimized out, without a single variable. **Even in this case, the constant variables are addressable.** – Nawaz Apr 07 '13 at 13:58
  • @Nawaz It is your point 3) which I disagree with. You can take the address of a variable to your heart's content, but if you never *use that address in an observable way*, then the compiler can optimise it out. Why do you believe otherwise? – JBentley Apr 07 '13 at 14:00
  • @JBentley: Are you implying that the constant variables are not addressable? **Please read the answer in the context of the question** which asks *How does a compiler get a const's address in C++?* – Nawaz Apr 07 '13 at 14:01
  • @Nawaz I think it's your turn to re-read the answer, in particular: "In a case like your... it can't do it". That is clearly, 100%, wrong, however much you try to argue semantics. – JBentley Apr 07 '13 at 14:04
  • @JBentley: Is it not addressable? Please answer, Yes or No. – Nawaz Apr 07 '13 at 14:07
  • @Nawaz That is irrelevant to my point. It is wrong to state that in the OP's code, the variable can't be optimised out. – JBentley Apr 07 '13 at 14:07
  • @JBentley: No. It is a matter of expression. Untill you attempt to express it, you will not see the problem with your thought. Please answer. Is it not addressable? – Nawaz Apr 07 '13 at 14:08
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/27722/discussion-between-jbentley-and-nawaz) – JBentley Apr 07 '13 at 14:09
1

compiler might do many tricks that it is allowed to do up to the point when it will affect visible behaviour of the program (see as-if rule). So it might not allocate storage for const object const int a = 99; ,but in the case when you take an address of variable - it has to be allocated some storage or at least pretended to be and you will get memory address which allows you to refer toa. code:

#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

so what we see is that the variable const int a = 99; is in fact built in machine code, do not reside in specific area of memory (there is no memory on the stack, the heap or the data segment allocated to it). Please correct me if I am wrong.

Community
  • 1
  • 1
4pie0
  • 29,204
  • 9
  • 82
  • 118