Go Premium for a chance to win a PS4. Enter to Win

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 650
  • Last Modified:

Why the output is 10 ? const int num = 20; (int &)num=10; cout<<(long &)num;

Hi.Experts:
i find:
     const int num = 20;
     (int &)num=10;
     cout<<(long &)num;
     cout<<(int &)num;
     cout<<num;
the assembly code in Release build:
00401000   push        0Ah
00401002   mov         ecx,offset std::cout (00427318)
00401007   call        std::basic_ostream<char,std::char_traits<char> >::operator<< (00401260)
6:                const int num = 20;
7:                (int &)num=10;
8:                cout<<(long &)num;
9:                cout<<(int &)num;
0040100C   push        14h
0040100E   mov         ecx,offset std::cout (00427318)
00401013   call        std::basic_ostream<char,std::char_traits<char> >::operator<< (00401030)
10:               cout<<num;
00401018   push        14h
0040101A   mov         ecx,offset std::cout (00427318)
0040101F   call        std::basic_ostream<char,std::char_traits<char> >::operator<< (00401030)

How do compiler to know  0Ah of "push 0Ah"????
0
TKD
Asked:
TKD
  • 9
  • 6
  • 5
  • +4
1 Solution
 
DexstarCommented:
@TKD:

> How do compiler to know  0Ah of "push 0Ah"????

This is interesting.  Look what happens when you comment out line #7:
      110:             const int num = 20;
      111:             //(int &)num=10;
      112:             cout<<(long &)num;
      00401490 6A 14            push        14h  
      00401492 B9 5C 8B 42 00   mov         ecx,offset std::cout (428B5Ch)
      00401497 E8 64 FE FF FF   call        std::basic_ostream<char,std::char_traits<char> >::operator<< (401300h)
      113:             cout<<(int &)num;
      0040149C 6A 14            push        14h  
      0040149E B9 5C 8B 42 00   mov         ecx,offset std::cout (428B5Ch)
      004014A3 E8 58 FE FF FF   call        std::basic_ostream<char,std::char_traits<char> >::operator<< (401300h)
      114:             cout<<num;
      004014A8 6A 14            push        14h  
      004014AA B9 5C 8B 42 00   mov         ecx,offset std::cout (428B5Ch)
      004014AF E8 4C FE FF FF   call        std::basic_ostream<char,std::char_traits<char> >::operator<< (401300h)

Which is what I would expect.  I have no idea where it gets the value of 0Ah in your example, or why it only uses it for the first call.  Can anyone fill here?

Dex*


Dex*
0
 
Gratch06Commented:
>cout<<(long &)num;

At this point, you are calling the function that handles the overloaded << operator, and C++ passes values to functions by pushing them onto the stack, then calling the function.  The 10 comes from your earlier declaration of num.

>(int &)num=10;

Minor point of clarity, pretty sure you already have this, but: 0Ah = 0x0A = 0A hexadecimal = 10 decimal.
0
 
TKDAuthor Commented:
const int num = 20;
(int &)num=10;
cout<<(long &)num;
cout<<(int &)num;
cout<<num;

if the output of "cout<<(long &)num;" is 10,
why isn't the ouput 10 of cout<<(int &)num; and cout<<num ?
Does num have memory in compile-time???
????
0
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
Gratch06Commented:
Having obviously misunderstood the depth of the question the first time, I'll go again from a different angle.

Adjusted code, making all types explicit and giving explanation for each step.
>const int num = 20;   //declare a constant integer named 'num' and give it the value of 20
>(int &)num=10;         //change the address of num to 10
>cout<<(long &)num; //print out the address of num, if it were a long
>cout<<(int &)num;    //print out the address of num, if it were an int
>cout<<(const int)num; //print out the value of num

Changing the final line to cout<<(const int&)num prints out 10, just as would be expected.

My only problem is on the final instruction...if we're changing the address of num in step 2, why would it copy the value of 20?  Wouldn't this variable be theoretically garbage?
0
 
DexstarCommented:
@Gratch06:

We should have made this clear before...  This question is kind of a continuation of this question:
http://www.experts-exchange.com/Programming/Programming_Languages/Cplusplus/Q_20811368.html

Where we established that "num", because it is a const, doesn't have any memory addresses.  The compiler explicitly uses 0Ah wherever we used num (almost like a #define).

The problem is, it explicitly uses the value 14h for the first call, and then 0Ah for the rest of the calls.  That's what we're trying to figure out.

Dex*
0
 
andrewjbCommented:
Interestingly, Borland C++ Builder gives an output of 10, 10 , 20...

0
 
PhilipNicolettiCommented:
From The ISO C++ Standard, Section 7.1.5.1 The cv-qualifiers :

4 Except that any class member declared mutable (7.1.1) can be modfied, any
attempt to modify a const object during its lifetime (3.8) results in undefined
behavior.

So you can not predict what the results will be. Different compilers can give
different results. Different versions of the same compiler can give different
results. Different compiler options on the same compiler can give
different results.
0
 
IcykorpioCommented:
nope...

NUM does take an entry in the symbol table with the attribute as CONST during the lexcial analynizing process...and the compiler simply takes it out and fills it there...that's all~

Regards
Icykorpio

0
 
IcykorpioCommented:
sorry... I miss some lines of the question...
0
 
IcykorpioCommented:
The problem is, it explicitly uses the value 14h for the first call, and then 0Ah for the rest of the calls.  That's what we're trying to figure out.
==========================================

this is reasonable...when no type cast...compiler takes the const directly from the symbol table, so 14h...other wise(as here to a long) from the memory...then 0Ah...
0
 
IcykorpioCommented:
it is 0A for the first call and 14h for the rest calls...
0
 
IcykorpioCommented:
standards is standards but every specific implementation does have its own defined way
0
 
DexstarCommented:
Yeah, we see WHAT is going on, and we know the behaviour is undefined...  We just want to know WHY the compiler is using 10 for the first call and 20 for the other 2.

Dex*
0
 
rstaveleyCommented:
const isn't as "straight-talking" as #define. It looks like the third cout is treating num as a #define and the previous couts are not.
0
 
rstaveleyCommented:
...you get 101020 on GCC3.2 and 102020 on VC7.1 - different undefined interpretations, I guess.
0
 
IcykorpioCommented:
I have said why
0
 
DexstarCommented:
I still don't understand why it uses 20 for the first call and 10 for the other 2.  How is it picking which one to use when?

Dex*
0
 
andrewjbCommented:
Does it actually matter? You're doing something that's naughty and undefined, so don't do it. Apart from the achademic interest of why it does this, is there another reason you're interested?

It probably depends what day of the week it was when the compiler writers coded this :-)

0
 
DexstarCommented:
No, it doesn't actually matter, but yes, I still want to know for purely pedantic reasons.

Dex*
0
 
rstaveleyCommented:
Looking at the .asm generated by VC7.1, you see:
--------8<--------
; Line 7
      mov      DWORD PTR _num$[ebp], 20            ; 00000014H
; Line 8
      mov      DWORD PTR _num$[ebp], 10            ; 0000000aH
; Line 9
      mov      eax, DWORD PTR _num$[ebp]
      push      eax
      mov      ecx, OFFSET FLAT:?cout@std@@3V?$basic_ostream@DU?$char_traits@D@std@@@1@A
      call      ??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QAEAAV01@J@Z ; std::basic_ostream<char,std::char_traits<char> >::operator<<
; Line 10
      push      20                              ; 00000014H
      mov      ecx, OFFSET FLAT:?cout@std@@3V?$basic_ostream@DU?$char_traits@D@std@@@1@A
      call      ??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QAEAAV01@H@Z ; std::basic_ostream<char,std::char_traits<char> >::operator<<
; Line 11
      push      20                              ; 00000014H
      mov      ecx, OFFSET FLAT:?cout@std@@3V?$basic_ostream@DU?$char_traits@D@std@@@1@A
      call      ??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QAEAAV01@H@Z ; std::basic_ostream<char,std::char_traits<char> >::operator<<
--------8<--------
In VC7.1, the "constant" 20 is saved on the stack and then overwritten by 10. That value is then using for the cout - see line 9.  Subsequent couts push immediates (20), which is what you'd expect fom a #define'd constant. The outcome is similar to TKD's, but it is interesting to see that it isn't using an immediate for the 10, where TKD's compiler does push an immediate.

Like Dexstar, I find this interesting, because it shines some light on the oddness of const in C++ in compiler implementations. C's #define is much more transparent than C++'s const. A C++ const may be an immediate or something in the data segment (or 'CONST' segment)... or in this case, the stack.
0
 
DexstarCommented:
@rsastevely:  Turn on optimizations for your compiler, and you'll get something more like what I posted above (I'm also using VC 7.1).  D*
0
 
rstaveleyCommented:
You're right, Dextar.

The unoptimised disassembly sheds some light on the method behind the madness :-)

It is a similar story for GCC3.2 without optimisations:
--------8<--------
        movl    $20, -4(%ebp)
        movl    $10, -4(%ebp)
        subl    $8, %esp
        pushl   -4(%ebp)
        pushl   $_ZSt4cout
.LCFI3:
        call    _ZNSolsEl
        addl    $16, %esp
        subl    $8, %esp
        pushl   -4(%ebp)
        pushl   $_ZSt4cout
        call    _ZNSolsEi
        addl    $16, %esp
        subl    $8, %esp
        pushl   $20
        pushl   $_ZSt4cout
        call    _ZNSolsEi
--------8<--------

Except that the 10 value is taken from the stack for cout<<(int &)num as well as cout<<(long &)num.

Interesting to see that unoptimised GCC pushes directly from the stack

    pushl -4(%ebp)

...and VC7.1 uses EAX as an intermediary - i.e. the equivalent of...

   movl    -4(%ebp),eax
   pushl   eax

When GCC is optimised (-O3), it pushes immediates just like VC.
0
 
DexstarCommented:
@rstaveley:  This question has kinda been moved here:
http://www.experts-exchange.com/Programming/Programming_Languages/Assembly/Q_20812395.html

Look at my last post where I tried it with a bunch of different type of casts.  Sometimes it uses 10, and sometimes is ues 20.

Dex*
0
 
DexstarCommented:
@TKD:  Have you gotten a satisfactory answer to this question?  I know I have.  I'm going to close out the other question, but I'm not sure how you want to handle this one.
0
 
TKDAuthor Commented:
Yes. I get the answer from
http://www.experts-exchange.com/Programming/Programming_Languages/Assembly/Q_20812395.html
Thanks for ur discuss and helps!!
I learn a lot!
THX.

0
 
rstaveleyCommented:
It has been an interesting diversion. It beats doing real work :-)
0
 
DexstarCommented:
Yeah, I especially appreciate the posting of the code generated by gcc.  I don't use that compiler at all, so I would not have been able to see that otherwise.

Dex*
0

Featured Post

Ask an Anonymous Question!

Don't feel intimidated by what you don't know. Ask your question anonymously. It's easy! Learn more and upgrade.

  • 9
  • 6
  • 5
  • +4
Tackle projects and never again get stuck behind a technical roadblock.
Join Now