LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   A problem about the "const" of C++ (https://www.linuxquestions.org/questions/programming-9/a-problem-about-the-const-of-c-4175516390/)

dy20082250 08-26-2014 03:21 AM

A problem about the "const" of C++
 
#include "stdafx.h"
#include <iostream.h>


int main(int argc, char* argv[])

{

const int i=10;

int *pi = (int *) &i;
const int *pii = &i;

int j=99;
int *pj=&j;

*pj=10000;

*pi=33;


cout << i << endl;

cout << *pi << endl;

cout << pi << endl;

cout << pii << endl;

cout << *pii << endl;

cout << j << endl;




return 0;
}




the result is following:

10
33
0x0012FF7C
0x0012FF7C
33
10000


why can not i change "i" through the pointer pi



but can change "j" through the pointer pj;


the value of "pi" and "pii" is the address of "i"

NevemTeve 08-26-2014 03:50 AM

Why would you change the value of a 'const'?
I'd say you were asking for trouble and you got it all right.
Still, you can try 'const volatile int i = 10;'

dy20082250 08-26-2014 04:26 AM

Quote:

Originally Posted by NevemTeve (Post 5227397)
Why would you change the value of a 'const'?
I'd say you were asking for trouble and you got it all right.
Still, you can try 'const volatile int i = 10;'

Because some net friend tell me that i can do that

besides ,i think the reason is not important

i exactly get the adress of "i",and assin it to "pi"

and i change "*pi", we can see that the content of the adress of "i" is changed

but when i look up it through "i", it can not show the change of the content.


why why why why why why why why why why why why why ?

NevemTeve 08-26-2014 04:55 AM

Cos cos cos cos cos cos cos cos the compiler thought it might safely use literal value 10 for i, for it is a 'const'

Note: you would get a bit more clear messages if you used printf:

Code:

printf ("i is at %p, value=%d\n", (void *)&i, i);
printf ("pi=%p, *pi=%d\n", (void *)pi, *pi);


dy20082250 08-26-2014 05:09 AM

Quote:

Originally Posted by NevemTeve (Post 5227426)
Cos cos cos cos cos cos cos cos the compiler thought it might safely use literal value 10 for i, for it is a 'const'

Note: you would get a bit more clear messages if you used printf:

Code:

printf ("i is at %p, value=%d\n", (void *)&i, i);
printf ("pi=%p, *pi=%d\n", (void *)pi, *pi);




You are right maybe ,the keypoint is the literal value

the content of the address 0x0012FF7c has been changed

but the compiler tie "i" to "10";

pan64 08-26-2014 05:40 AM

looks like an error for me:
int *pi = (int *) &i;
if i was a register or used inline, there is no address of.

mina86 08-26-2014 06:16 AM

Quote:

Originally Posted by dy20082250 (Post 5227418)
Because some net friend tell me that i can do that

You cannot. This invokes an undefined behaviour and compiler can do whatever it wants with such a code (including deleting all files from your home directory). Your code did not blow up only because the const variable has been declared on the stack. If you use “static const int i = 10;” instead compiler will put the object in a read only segment and trying to change it will result in segmentation fault.

Quote:

Originally Posted by pan64 (Post 5227438)
looks like an error for me:
int *pi = (int *) &i;
if i was a register or used inline, there is no address of.

By taking address of the object, the code forces it to be placed somewhere in memory. If the address was not taken, the variable would be inlined indeed.

dy20082250 08-26-2014 06:33 AM

Quote:

Originally Posted by mina86 (Post 5227458)
You cannot. This invokes an undefined behaviour and compiler can do whatever it wants with such a code (including deleting all files from your home directory). Your code did not blow up only because the const variable has been declared on the stack. If you use “static const int i = 10;” instead compiler will put the object in a read only segment and trying to change it will result in segmentation fault.


By taking address of the object, the code forces it to be placed somewhere in memory. If the address was not taken, the variable would be inlined indeed.



I have tried what you said and defined a global variable ,the program was terminated


but i don't understand what you say about "inline"

what's that mean?

pan64 08-26-2014 06:41 AM

Quote:

Originally Posted by mina86 (Post 5227458)
By taking address of the object, the code forces it to be placed somewhere in memory. If the address was not taken, the variable would be inlined indeed.

just try to run the same code using volatile i as it was suggested by "NevemTeve"

mina86 08-26-2014 07:35 AM

Quote:

Originally Posted by dy20082250 (Post 5227464)
but i don't understand what you say about "inline"
what's that mean?

Use -S to see assembly output of your program and you'll see:
Code:

$ cat a.c
#include <stdio.h>
int main(void) {
        const int i = 10;
        printf("%d\n", i);
        return 0;
}
$ gcc -S -O2 -fomit-frame-pointer a.c
$ cat a.s  # somehow shortened
.LC0:        .string        "%d\n"
main:        subq        $8, %rsp
        movl        $10, %edx    /* i == 10 argument */
        movl        $.LC0, %esi  /* format argument */
        movl        $1, %edi
        xorl        %eax, %eax
        call        __printf_chk
        xorl        %eax, %eax
        addq        $8, %rsp
        ret

As you can see, the “i” variable is *never* created. The compiler simply knows that “i == 10” therefore whenever “i” is used, it simply passes literal “10”.

pan64 08-26-2014 07:55 AM

Quote:

Originally Posted by mina86 (Post 5227490)
As you can see, the “i” variable is *never* created. The compiler simply knows that “i == 10” therefore whenever “i” is used, it simply passes literal “10”.

so in this case what is the address of i? Why can I have it?

NevemTeve 08-26-2014 08:22 AM

If you take its address, the compiler will assign a memory location on the stack, but it still has the right to use the literal value of 10 whenever you use 'i'.

mina86 08-26-2014 09:22 AM

Quote:

Originally Posted by pan64 (Post 5227496)
so in this case what is the address of i? Why can I have it?

Code:

$ cat a.c &&  gcc -S -O2 -fomit-frame-pointer a.c && cat a.s
#include <stdio.h>
int main(void) {
        const int i = 10;
        printf("i = %d, &i = %p\n", i, (void*)&i);
        return 0;
}
# Again, assembly source shortened a little
.LC0:        .string        "i = %d, &i = %p\n"
main:        subq        $24, %rsp
        movl        $10, %edx      /* i argument */
        movl        $.LC0, %esi    /* format argument */
        leaq        12(%rsp), %rcx  /* rcx = rsp + 12 == &i argument */
        movl        $1, %edi
        xorl        %eax, %eax
        movl        $10, 12(%rsp)  /* initialise i to 10 */
        call        __printf_chk
        xorl        %eax, %eax
        addq        $24, %rsp
        ret

So compiler created a space on stack for the variable, but when passing i argument, just used literal 10.

sundialsvcs 08-26-2014 10:32 AM

Quote:

Originally Posted by dy20082250 (Post 5227464)
but i don't understand what you say about "inline"

what's that mean?

Quite honestly, friend, you need to "mash the Pause button" on your premature attempts to write C++, with or without the helpful-advice of your compadre, and spend some time learning about the language! There are plenty of books, online and otherwise, which talk about the various language features, and you need to stop and read them! :tisk:

I'm trying to say that in the very nicest possible way, and with the purpose of being helpful. (This is not "RTFM.™") Because, what you're doing right now is banging your head against things that you barely (if at all) understand, when the ability to fully understand them will only take a little more of the time that you are wasting right now. Quit stumbling around in the dark: turn on the lights, get a map, and stop and read it. You have a well-defined goal to reach ("understanding"), and what you're doing right now is a hopelessly-inefficient non-method of getting there.

psionl0 08-26-2014 12:15 PM

Quote:

Originally Posted by mina86 (Post 5227538)
So compiler created a space on stack for the variable, but when passing i argument, just used literal 10.

That looks like a compiler bug to me.

Either it should not create a memory location for the constant - meaning that attempting to set a pointer to the address of the constant gives an error message

or

It creates a memory location to store the value of the constant but any attempt to change the contents of that memory location would result in an error message.

Of course, in normal programming practice, once you have decided that something is to be a constant, there should be no reason to refer to its address nor to change its value so this unusual situation would not crop up.


All times are GMT -5. The time now is 12:07 AM.