0

I was trying to understand the cdecl calling convention and I stumbled on this weird behaviour.

As per cdecl standards, the calling function stores the parameters from Right to Left on to the stack and then calls the target function. So I assumed the parameters would be evaluated left to right since that would resemble a stack flow or it could still evaluate from right to left given the cdecl convention for storing the parameters.

But the output of the below program has baffled me. Below is a simple program I wrote to understand the evaluation of parameters.

void fun (int a, int b, int c) {    
    printf("a: %d, b: %d, c: %d\n", a, b, c);
}    

int main()    
{
    int i = 2; 
    fun(i, i++, i);
}  

Expected Output: a: 3, b: 2, c: 2 or a: 2, b: 2, c: 3

Actual Output: a: 3, b: 2, c: 3

 gcc --version
 gcc (Ubuntu 4.8.2-19ubuntu1) 4.8.2
 Copyright (C) 2013 Free Software Foundation, Inc.
 This is free software; see the source for copying conditions.  There is NO
 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

Can someone throw some light on this?

user207421
  • 305,947
  • 44
  • 307
  • 483
vinodkri
  • 33
  • 4
  • 1
    See the other question, it clearly explains why "stores the parameters from Right to Left" is completely unrelated to the order of evaluation. – Ben Voigt Feb 10 '15 at 05:09
  • This code causes undefined behaviour (due to mixing of `i` and `i++`) regardless of any order of evaluation or parameter storage issues, [see here](http://stackoverflow.com/questions/949433/why-are-these-constructs-using-undefined-behavior) – M.M Feb 10 '15 at 06:28

1 Answers1

0

This is a common confusion: there are two unary operators that increment an a number: var++ and ++var. var++ will add one to the variable after passing the value of the variable to the function, while ++var will add one before the data is passed to the function.

Try changing the position of the ++ operator and see what happens.

Quick example:

#include <iostream>
int main() {
     int i = 5;
     std::cout << i << std::endl; //Prints "5"
     std::cout << i++ << std::endl; //Also prints "5", but after i is 6
     std::cout << ++i << std:: endl; //Prints "7"
ahjohnston25
  • 1,915
  • 15
  • 36
  • I changed it to fun (i, i, i++); i got the following ouput.. a: 3, b: 3, c: 2. This make sense to me since I can conclude that the evaluation is happening Right to Left.. But in the Previous case.. Its ambiguous. – vinodkri Feb 10 '15 at 05:02
  • Not necessarily "after the line of code is over". Simply "the value of the postincrement is the old value of the variable". – Ben Voigt Feb 10 '15 at 05:04
  • 1
    And now you're encouraging use of undefined behavior :( – Ben Voigt Feb 10 '15 at 05:04
  • @BenVoigt I'm trying to make the use of pre versus post unary increment clear to the asker. I'll erase my comment as that was unintended. – ahjohnston25 Feb 10 '15 at 05:06
  • @BenVoigt regard "after the line is over" I should have been clear that that particular phrasing was an oversimplification for the sake of the asker. I'll edit my answer accordingly. – ahjohnston25 Feb 10 '15 at 05:07
  • If i change it to fun(i,++i,i) i get the following output: a:3 b:3 c:3.. So does that mean if any parameter needs some evaluation will be evaluated and rest will be passed or rather will be pushed on to the stack ? – vinodkri Feb 10 '15 at 05:08
  • 1
    @VinKris: No, there is no such guarantee. Read the answers to the question I closed yours as a duplicate of. – Ben Voigt Feb 10 '15 at 05:09
  • @VinKris You shouldn't rely on using `++` as a prefix when passing to a function. As @BenVoigt was reminding me, doing so is undefined behavior (so the compiler can choose how to handle that situation if at all). – ahjohnston25 Feb 10 '15 at 05:09
  • BenVoigt, ahjohnston25 thanks for the quick answers.. – vinodkri Feb 10 '15 at 05:12