Thread: Stack push order for function arguments

  1. #1
    (?<!re)tired Mario F.'s Avatar
    Join Date
    May 2006
    Location
    Ireland
    Posts
    8,446

    Stack push order for function arguments

    A quick experiment revealed function arguments to be pushed onto the stack from "right to left".

    void test (int a, int b);
    Pushes b first and only then a. Local variables are otherwise pushed as expected following the order of declaration.

    I'm just curious as to why arguments are pushed this way and if I can expect this to be standard behavior across compliant compilers.

    And since we are on the subject, probably a silly question... If this is indeed standard behavior doesn't this mean order of argument initialization is fixed and thus a language feature that allowed default values to evaluate formal arguments would be possible?
    Something like void test (int a = b + c, int b = c, int c = 1);

    I'm unsure of the utility of such feature... not to mention a, b and c haven't been declared at that point... but the thought crossed my mind.
    Originally Posted by brewbuck:
    Reimplementing a large system in another language to get a 25% performance boost is nonsense. It would be cheaper to just get a computer which is 25% faster.

  2. #2
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by Mario F. View Post
    I'm just curious as to why arguments are pushed this way and if I can expect this to be standard behavior across compliant compilers.
    They are pushed right to left so that the leftmost argument is always at the top of the stack in the called function's frame. This is to allow C-style variadic functions like printf() to work properly.

    You can count on it working that way, unless you use some compiler feature to change things.

    And since we are on the subject, probably a silly question... If this is indeed standard behavior doesn't this mean order of argument initialization is fixed and thus a language feature that allowed default values to evaluate formal arguments would be possible?
    Just because the arguments are PUSHED in that order doesn't mean they must be EVALUATED in that order. You can't assume anything about the order of evaluation.

  3. #3
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Indeed, as brewbuck says, it doesn't say anything about ORDER of evaluation, only about the order the arguments are pushed.

    I used a peice of code similar to this:
    Code:
        func1(func2(), func3());
    I expected func3() and func2() to be called "in order", which worked fine on the first compiler I used (gcc on sparc), but when I later tried the same project on x86, it failed - func2 and func3 both have side-effects, and when they are called in the wrong order, things don't work right. So I ended up calling them explicitly, with temp variables to pass to func1().

    --
    Mats

  4. #4
    Deathray Engineer MacGyver's Avatar
    Join Date
    Mar 2007
    Posts
    3,210
    With the different calling conventions, there are multiple ways of passing variables around. This is just the standard one with C/C++.

  5. #5
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by MacGyver View Post
    With the different calling conventions, there are multiple ways of passing variables around. This is just the standard one with C/C++.
    True, x86-64 for example passes up to 6 args in registers, rather than on the stack - these six are of course selected "left to right".

    --
    Mats

  6. #6
    Registered User
    Join Date
    Oct 2001
    Posts
    2,129
    afaik, you can't rely on the calling convention. If you want a particular convention, you'll have to use a compiler-dependent option, like __cdcel or __stdcall or whatever it's called.

  7. #7
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by robwhit View Post
    afaik, you can't rely on the calling convention.
    I don't have the spec with me now, but I'm reasonably sure it does say that a conforming implementation pushes right to left. It might even specify that the caller saves, but I'm not as certain about that one.

  8. #8
    Registered User
    Join Date
    Jul 2007
    Location
    Naperville, Illinois, USA (near Chicago)
    Posts
    7
    Quote Originally Posted by Mario F. View Post
    A quick experiment revealed function arguments to be pushed onto the stack from "right to left".

    [...]

    I'm just curious as to why arguments are pushed this way and if I can expect this to be standard behavior across compliant compilers
    For what little it is worth, early C compilers used YACC to do the parsing. It was convenient to make the rules left recursive, which meant the arguments were collected from right to left. This trickled down to low-level code generation. The original C++ compiler (known as "cfront") just used C macros to add the C++ features to C. So the mechanism became a de facto behavior, but not de jure standard.

    Then it was standardized because it meant nobody had to change their compilers...

  9. #9
    Registered User
    Join Date
    Oct 2001
    Posts
    2,129
    I can't even find a reference to the subject of calling conventions, much less specifying which convention is the standard. If somebody would like to give a quote from a standard, that would be great.

    Otherwise:
    Quote Originally Posted by ISO/IEC 9899:TC2 Section 1.2
    This International Standard does not specify
    — the mechanism by which C programs are transformed for use by a data-processing system;
    edit: I just realized this was the C++ board.
    Last edited by robwhit; 07-31-2007 at 12:37 AM.

  10. #10
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    For Win32: http://www.unixwiz.net/techtips/win32-callconv.html

    There used to be the _PASCAL_ calling convention but I believe that was only for 16-bit applications. Most of the Windows API used this convention at one time.

    The only time the order ever mattered to me is when I was mixing assembly language with C. I had to know in what order the parameters were pushed onto the stack in order to use them correctly.

  11. #11
    Registered User
    Join Date
    May 2003
    Posts
    1,619
    Quote Originally Posted by brewbuck View Post
    I don't have the spec with me now, but I'm reasonably sure it does say that a conforming implementation pushes right to left. It might even specify that the caller saves, but I'm not as certain about that one.
    I'm fairly certain the standard doesn't even require that there BE a stack, much less that the stack is to be used for parameters, or the parameters must be passed in a particular order.

    The right-to-left is convention, but it's not required.
    You ever try a pink golf ball, Wally? Why, the wind shear on a pink ball alone can take the head clean off a 90 pound midget at 300 yards.

  12. #12
    (?<!re)tired Mario F.'s Avatar
    Join Date
    May 2006
    Location
    Ireland
    Posts
    8,446
    Thanks for the info folks... however... one question:

    Brewbuck, you mention objects being pushed into the stack in a specific order, doesn't mean they were evaluated in that order. Help me understand that... In order for an object to be pushed onto the stack doesn't it need to be first evaluated?

    Say, a = 2+5 and b = 2+5. If b is pushed before a, doesn't b need to be evaluated before a? If a were to be evaluated first, where would the result of the evaluation go while it waits for b to be pushed?
    Originally Posted by brewbuck:
    Reimplementing a large system in another language to get a 25% performance boost is nonsense. It would be cheaper to just get a computer which is 25% faster.

  13. #13
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by Mario F. View Post
    Say, a = 2+5 and b = 2+5. If b is pushed before a, doesn't b need to be evaluated before a? If a were to be evaluated first, where would the result of the evaluation go while it waits for b to be pushed?
    Some temporary location.

    Code:
    tmp1 = eval(a)
    tmp2 = eval(b)
    
    push tmp2
    push tmp1
    In practice the arguments are usually evaluated in the order they are pushed. But there are legitimate reasons to do otherwise.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Help With Stacks
    By penance in forum C Programming
    Replies: 7
    Last Post: 10-09-2005, 02:47 PM
  2. Stack using push and pop
    By silicon in forum C++ Programming
    Replies: 5
    Last Post: 11-03-2003, 04:54 PM
  3. Stack manipulation
    By JJD in forum C Programming
    Replies: 1
    Last Post: 10-08-2002, 11:44 AM
  4. What am I doing wrong, stack?
    By TeenyTig in forum C Programming
    Replies: 2
    Last Post: 05-27-2002, 02:12 PM
  5. inputting line of text vs. integers in STACK
    By sballew in forum C Programming
    Replies: 17
    Last Post: 11-27-2001, 11:23 PM