Thread: Returning multiple values

  1. #1
    Rad gcn_zelda's Avatar
    Join Date
    Mar 2003
    Posts
    942

    Returning multiple values

    Is it possible to return multiple values from a function?

    ex.
    Code:
    char such(void)
    {
          stuff
          return a;
          return b;
    }
    
    int main()
    {
           c,d = such();
    }
    or something like that?

  2. #2
    C++ Developer XSquared's Avatar
    Join Date
    Jun 2002
    Location
    Ontario, Canada
    Posts
    2,718
    The only way to do that would be a struct or just passing the variables by reference:
    Code:
    void foo( char &a, char &b ) {
        stuff;
        a = value;
        b = value2;
    }
    
    int main( void ) {
        int a, b;
        foo( a, b );
    }
    Naturally I didn't feel inspired enough to read all the links for you, since I already slaved away for long hours under a blistering sun pressing the search button after typing four whole words! - Quzah

    You. Fetch me my copy of the Wall Street Journal. You two, fight to the death - Stewie

  3. #3
    Rad gcn_zelda's Avatar
    Join Date
    Mar 2003
    Posts
    942
    oh. thanks...I'm no good with pointers and such

  4. #4
    Registered User
    Join Date
    Apr 2003
    Posts
    2,663
    There are ways to return multiple values from a function, but you can't do it in a return statement. How are you with arrays? Try this:
    Code:
    #include <iostream>
    using namespace std;
    
    void func(double number[])
    {
    	number[0] = 20.0;
    	number[1] = 30.0;
    }
    
    int main()
    {
    	double data[2];
    	data[0] = 6.0;
    	data[1] = 7.0;
    
    	func(data);
    
    	cout<<data[0]<<endl<<data[1]<<endl;
    
    	return 0;
    }
    Last edited by 7stud; 07-31-2003 at 11:25 PM.

  5. #5
    Registered User
    Join Date
    May 2003
    Posts
    14
    For this to work you'd still need to pass by ref.
    Code:
    void func(double &number[])

  6. #6
    Registered User
    Join Date
    Apr 2003
    Posts
    2,663
    hsv,

    Try again.

  7. #7
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    There is a way to return multiple values but I do not recommend doing this.

    In C and on x86 platforms the C compiler looks at the (e)ax register for integral return values and at st(0) for floating point returns.

    It is possible to simply place values in registers to return multiple values.

    Code:
    void ReturnFoo(int a,int b,int c,int d)
    {
      _AX=a+b;
      _BX=c+d;
    }
    Even though this is void, we know this function returns a value - not a good practice at all because it obfuscates the purpose of the function and violates several rules of C programming. But in theory it is the same as placing a return type in front of the function name - EXCEPT that the compiler will not be able to do MyVar=MyFoo(a,b,c,d) - because you declared MyFoo as void so the compiler says - hey you dummy you can't return a value from a void function. Even though you have placed your value in (e)ax the compiler does not know this and so will yell at you all day long.

    or

    Code:
    int ReturnFoo(int a,int b,int c,int d)
    {
      _BX=c+d;
      return (a+b);
    }
    This code notifies the C compiler that an integral value will be returned - so it places the result of a+b into (e)ax. So when you do MyVar=MyFoo(a,b,c,d) the compiler knows upon returning from MyFoo it should look in (e)ax for the value and place that into the memory location or variable known as MyVar. Everybody gets along this way and this is the correct prototype.


    Nearly the same as the following asm code. I say nearly because in the disassembly you will not see ARG and you will not see the variable names - you will see stack locations.
    Code:
    _ReturnFoo    proc
    ARG a:WORD,b:WORD,c:WORD,d:WORD
      push  bp
      mov   bp,sp
    
      mov   bx,[c]
      add    bx,[d]
      mov   ax,[a]
      add   ax,[b]
    
      pop   bp
      ret
    _ReturnFoo     endp
    However there are better ways to do this as have been described in this thread. Usually returning a pointer to a structure is the best way to do it. C is not really returning an array, but a pointer to an array - the pointer resides in (e)ax - even for floating point arrays.

    But the reason that my example will work is because the registers are not on the stack, so you can set their value and when your function returns to the caller - the registers should theoretically hold the value you placed in them, unless C has done something else with those registers. But I seriously doubt that C would mess with the explicit return registers after returning from a function. We know for sure that C does nothing with (e)ax and st(0) or else we could not return values from functions - so logically we could say that C also will not alter any other explicit return value registers or floating point registers. However I would not return values in any other registers because you will run into trouble.

    The only thing that is popped off the stack on a return are local variables so you should be safe with the above code. However it is not good practice and I don't recommend it because C provides a much better system for doing this.

    Just food for thought.
    Last edited by VirtualAce; 08-01-2003 at 07:22 AM.

  8. #8
    Registered User
    Join Date
    Apr 2003
    Posts
    2,663
    Hey Bubba,

    Thanks for repeatedly demonstrating your knowledge of assembly language in your recent posts, however this is a C++ forum, so you can stop posting answers discussing assembly language--it is not at all helpful. In the future, try to speak to your audience, which in this case is someone who has clearly stated that they don't understand pointers and references.
    Last edited by 7stud; 08-01-2003 at 10:41 AM.

  9. #9
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    Yeah Bubba!!! Damn that guy.

    What was he thinking?

  10. #10
    ¡Amo fútbol!
    Join Date
    Dec 2001
    Posts
    2,138
    Since C++ allows inline assembly, I think his post is valid.

  11. #11
    Comment your source code! Lynux-Penguin's Avatar
    Join Date
    Apr 2002
    Posts
    533
    actually if you looked at bubba's code...
    2/3 of it was C++

    and he makes a VALID and GREAT point, directly answering the question. I don't see what the problem is.

    I enjoy looking at his ASM.

    Now, as an answer to the question.
    Very VERY easily.

    Code:
    struct ret_mult
    {
    	int first;
    	int second;
    };
    
    ret_mult returner(int a,int b,int c,int d)
    {
    	ret_mult ret = {a+b,c+d};
    	return ret;
    }
    and a quick question for bubba:
    I thought the parameters were in eax...

    like
    Code:
        movl  $0x1, %eax
        call  do_something
    -LC
    Asking the right question is sometimes more important than knowing the answer.
    Please read the FAQ
    C Reference Card (A MUST!)
    Pointers and Memory
    The Essentials
    CString lib

  12. #12
    Crazy Fool Perspective's Avatar
    Join Date
    Jan 2003
    Location
    Canada
    Posts
    2,640
    Originally posted by hsv
    For this to work you'd still need to pass by ref.
    Code:
    void func(double &number[])
    arrays are always passed by reference. & or not

  13. #13
    An array is just a non-dynamically allocated pointer to a section of memory.

    char a[10];
    char * p = new char [10];

    a[0] = 'A';
    p[0] = 'P';

    See? All the same thing. Therefor the memory pointer to can be altered by the value of the pointer itself could not be. Personally, I'd pass by reference to avoid confusion and to make the intent clear anyhow.

    >>so you can stop posting answers discussing assembly language--it is not at all helpful.

    Yes. It is... And stop being obnoxious.

    Why would you need a function to return multiple values anyhow? More than likely what you need is to pass in a few variables by reference and have your function adjust them.
    "There's always another way"
    -lightatdawn (lightatdawn.cprogramming.com)

  14. #14
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    Code:
    int ReturnFoo(int a,int b,int c,int d)
    {
      _BX=c+d;
      return (a+b);
    }
    Parameters in EAX?
    Lynux - the parameters to any function lie at positive offsets to EBP. This is because before the function is called, the parameters are pushed onto the stack and the stack pointer is altered. Any local variables will lie at negative offsets to EBP - thanks a million to Compuboy from flashdaddee for reminding me of this. All explicit return registers are basically undefined on entry into a function EXCEPT when said function expects certain values in EAX,EBX,ECX,EDX, etc. But those functions that do not use those registers are free to place any values in them they want. Try it and see. Enter a function w/o placing values in the explicit return registers and then inside of the function, print the register values. You will see that they contain the last value placed in them which means the function call did not touch them.

    Most DOS functions used AX (more like AH and AL) to represent function numbers or sub-function numbers for their OS functions. If you look at the RBIL - you will see that a lot of diff companies and programmers use the registers for a multitude of different things. There wasn't really a standard across all PCs AFAIK.

    Your AT&T syntax is killing me, but I'll forgive you just this once.



    Multiple values in one return statement
    I've always wondered why C allows you to return multiple values in one return statement - where the heck is the other value stored?? I have no idea. In your code Lynux (C code that is), I'm not sure what EAX would hold. I experimented with this before and I think that the compiler only returns the first value and ignores the rest of the line, but I could be wrong.

    Thanks
    And to everyone who did....thanks for supporting me. I was only trying to help.

    Be nice 7stud
    Perhaps I did get a bit carried away 7stud, but my post did not warrant your lack of respect for a fellow board member.

    Also I made a somewhat incorrect statement. Upon returning local variables are not popped off of the stack, parameters are. Local variables are dealt with by placing the base pointer (bp) into the stack pointer (sp). In this way the local variables will effectively disappear from the stack as other code writes over them on the stack. Popping local variables off of the stack would most certainly cause a crash UNLESS they were actually pushed onto it by a push instruction.

    Code:
    push bp
    mov  bp,sp
    sub   sp,10
    ...
    ...
    mov  sp,bp   ;restores the stack pointer to the base pointer  
                        ;effectively 'erasing' our local stack space
    
    ;popping anything else here would cause a crash - nothing else
    ;has been pushed onto the stack.
    
    pop  bp
    Sorry for the mixup.
    Last edited by VirtualAce; 08-02-2003 at 05:43 PM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Problem returning values in user defined format
    By manutdfan in forum C Programming
    Replies: 6
    Last Post: 11-20-2006, 05:20 PM
  2. test to see if multiple values are the same
    By squeaker in forum C++ Programming
    Replies: 3
    Last Post: 06-08-2006, 01:45 AM
  3. multiple values in #define(?) & counter placement
    By bnmwad in forum C Programming
    Replies: 2
    Last Post: 04-30-2006, 06:00 AM
  4. Returning Multiple Values from a function
    By Eddie K in forum C Programming
    Replies: 6
    Last Post: 03-12-2006, 01:18 PM
  5. Returning multiple types w/o a struct
    By Trauts in forum C++ Programming
    Replies: 8
    Last Post: 02-27-2003, 11:04 PM