Thread: Casting operator behavior

  1. #1
    Anti-Poster
    Join Date
    Feb 2002
    Posts
    1,401

    Casting operator behavior

    One of my friends recently showed me the following sample of code:
    Code:
    #include<iostream>
    
    using std::cout;
    using std::endl;
    
    class MyClass
    {
    public:
    	MyClass();
    	char buffer[4];
    	operator char *();
    };
    
    MyClass::MyClass()
    {
    	buffer[0] = 'a';
    	buffer[1] = 'b';
    	buffer[2] = 'c';
    	buffer[3] = '\0';
    }
    
    MyClass::operator char*()
    {
    	return buffer;
    }
    
    int main()
    {
    	MyClass test;
    	cout << test << endl;
    	return 0;
    }
    He said that the output was "abc", but I got the memory address instead. He was running on a Linux machine, so we're using different compilers. I'm using .Net. I'm sure that one behavior or the other is considered "correct". I tried looking through the standard, but I got bogged down in it pretty quickly. Which behavior is "correct"?
    If I did your homework for you, then you might pass your class without learning how to write a program like this. Then you might graduate and get your degree without learning how to write a program like this. You might become a professional programmer without knowing how to write a program like this. Someday you might work on a project with me without knowing how to write a program like this. Then I would have to do you serious bodily harm. - Jack Klein

  2. #2
    Registered User
    Join Date
    Jun 2004
    Posts
    722
    Maybe that memory adress is a pointer to your 1st char in the string.

  3. #3
    Anti-Poster
    Join Date
    Feb 2002
    Posts
    1,401
    It is. If you explicitly cast it as a char*, it works. My friend said that he didn't need to explicitly cast it for the output to be "abc".
    If I did your homework for you, then you might pass your class without learning how to write a program like this. Then you might graduate and get your degree without learning how to write a program like this. You might become a professional programmer without knowing how to write a program like this. Someday you might work on a project with me without knowing how to write a program like this. Then I would have to do you serious bodily harm. - Jack Klein

  4. #4
    Registered User
    Join Date
    Sep 2001
    Posts
    4,912
    So am I right in summing your question up as this?:

    If you pass cout a pointer to the first element of a C-style string, will it output the hexadecimal memory address or the C-style string, according to standard behavior?

  5. #5
    Registered User Micko's Avatar
    Join Date
    Nov 2003
    Posts
    715
    I must admit it is an interesting isuuse, and of course it cannot be seen frequently.
    I'll borrow explanation from Bjarne Stroustrup:
    "A member
    function X : : operator T(), where T is a type name, defines a conversion from X to T."

    Code:
    class Tiny {
    char v;
    void assign(int i) { if (i&~077) throw Bad_  range() ; v=i; }
    public:
    class Bad_  range{ };
    Tiny(int i) { assign(i) ; }
    Tiny& operator=(int i) { assign(i) ; return *this; }
    operator int() const { return v; } / / conversion to int function
    };
    The range is checked whenever a Tiny is initialized by an int and whenever an int is assigned to
    one. No range check is needed when we copy a Tiny, so the default copy constructor and assignment
    are just right.
    To enable the usual integer operations on Tiny variables, we define the implicit conversion from
    Tiny to int, Tiny: : operator int(). Note that the type being converted to is part of the name of the
    operator and cannot be repeated as the return value of the conversion function:
    Code:
    Tiny: : operator int() const { return v; } / / right
    int Tiny: :operator int() const { return v; } / / error
    Normally, if you give cout a pointer, it prints an address. But if the pointer is type char *, cout displays the pointed-to string. If you want to see the address of the string, you have to type cast the pointer to another pointer type, such as int *
    for example:
    Code:
    #include<iostream>
    using namespace std;
    int main()
    {
    	char str[]="micko";
    	cout<<str;
    	cout<<(int*)str;
    }
    You see the difference.
    Now the question is why this code:
    Code:
    cout << test;
    will print hexadecimal address (I've never figured out should I use the hexadecimal or just hexadecimal in this context )
    and this code
    Code:
    cout << (char*)test;
    will print string.

    To answer this let's call a little assembly in help:

    First code will produce something like this:
    Code:
    MyClass test;
    0043237E  lea         ecx,[test] 
    00432381  call        MyClass::MyClass (42E677h) 
    	cout <<test;
    00432386  lea         ecx,[test] 
    00432389  call        MyClass::operator char * (42E528h) 
    0043238E  push        eax  
    0043238F  mov         ecx,offset std::cout (49D244h) 
    00432394  call        std::basic_ostream<char,std::char_traits<char> >::operator<< (42E299h)
    Second code will produce something like this:

    Code:
    MyClass test;
    0043136E  lea         ecx,[test] 
    00431371  call        MyClass::MyClass (42D672h) 
    	cout <<(char*)test;
    00431376  lea         ecx,[test] 
    00431379  call        MyClass::operator char * (42D523h) 
    0043137E  push        eax  
    0043137F  push        offset std::cout (49B254h) 
    00431384  call        std::operator<< (42EE87h)
    As you can notice that different versions of operator<< are called.
    So I can assume that the reason (again the ) is impicit conversion which happens because of member function operator char*();

    Why it is different in Linux I don't have any clue, so I'll take this opportunity to ask guys with a lot more experience than me and especially with experience in Linux to try to asnwer this together.
    I'm looking forward to all constructive posts on this thread.
    Cheers!

    Micko

  6. #6
    Carnivore ('-'v) Hunter2's Avatar
    Join Date
    May 2002
    Posts
    2,879
    Perhaps the behaviour is undefined, and for some reason there is an implicit conversion done to a different datatype by your compiler, while your friend's compiler was smart enough not to do that. That might explain why the explicit typecast to char* solved the problem...

    [edit]
    Never mind. It would seem from the disassembly that the conversion to char* does get called.

    Perhaps if you defined the conversion operator as char[] instead of char*?

    Micko, if you could find out which version of cout gets called (trial and error? lol), that might help.
    [/edit]

    Of course, that is 100% guesswork and I offer no guarantee of accuracy
    Last edited by Hunter2; 10-11-2004 at 10:49 AM.
    Just Google It. √

    (\ /)
    ( . .)
    c(")(") This is bunny. Copy and paste bunny into your signature to help him gain world domination.

  7. #7
    S Sang-drax's Avatar
    Join Date
    May 2002
    Location
    Göteborg, Sweden
    Posts
    2,072
    Strange problem. Outputting a string is the correct behaviour, unless I'm really missing something here.
    I'm using .Net.
    So am I (2003), and I'm having the expected output.
    Last edited by Sang-drax : Tomorrow at 02:21 AM. Reason: Time travelling

  8. #8
    Registered User Micko's Avatar
    Join Date
    Nov 2003
    Posts
    715
    Quote Originally Posted by Sang-drax
    Strange problem. Outputting a string is the correct behaviour, unless I'm really missing something here.

    So am I (2003), and I'm having the expected output.
    I also use .net (2002) and I'm getting address of variable test and when I use (char*) then I get abc as output.
    It is an interesting issues isn't it?

  9. #9
    Anti-Poster
    Join Date
    Feb 2002
    Posts
    1,401
    Thank you all for your comments. It's relieving to know that I'm not just going crazy. I thought outputting the string was correct. I guess I'll just have to upgrade my compiler.
    If I did your homework for you, then you might pass your class without learning how to write a program like this. Then you might graduate and get your degree without learning how to write a program like this. You might become a professional programmer without knowing how to write a program like this. Someday you might work on a project with me without knowing how to write a program like this. Then I would have to do you serious bodily harm. - Jack Klein

  10. #10
    Carnivore ('-'v) Hunter2's Avatar
    Join Date
    May 2002
    Posts
    2,879
    It's probably just a compiler bug that was fixed in the later version of VC.NET. I was about to say so earlier, but then assumed that .NET is relatively bug free.
    Just Google It. √

    (\ /)
    ( . .)
    c(")(") This is bunny. Copy and paste bunny into your signature to help him gain world domination.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Casting
    By morvick in forum C++ Programming
    Replies: 2
    Last Post: 06-17-2007, 11:06 PM
  2. Casting Question (I think)
    By fayte in forum C Programming
    Replies: 6
    Last Post: 03-08-2006, 05:31 PM
  3. casting the system exstracted date into seperate ints
    By bazzano in forum C Programming
    Replies: 1
    Last Post: 08-30-2005, 12:17 AM
  4. Type casting
    By Lionmane in forum C Programming
    Replies: 28
    Last Post: 08-20-2005, 02:16 PM
  5. question about casting pointers/other types also??
    By newbie02 in forum C++ Programming
    Replies: 3
    Last Post: 08-07-2003, 05:01 AM