0

I was writing a very simple C/C++ program when I came across rather peculiar behavior.

When calling any two functions in sequence, they run in the order that they are called. For example, if I print out the string "hello" and then the string "world", I expect to get the string "helloworld" printed in the console, and that happens normally as expected.

However, when calling two functions within the call of another function they are executed in reverse order. This is demonstrated in the code below:

#include <iostream>
#include <stdarg.h>
void collector(int n, ...)
{
    va_list args;
    va_start(args, n);
    for (int i = 0; i < n; i++)
    {
        int elem = va_arg(args, int);
        // Do something with the returns
    }
    va_end(args);
    return;
}

int printAndReturn(const char *message)
{
    std::cout << message << std::endl;
    if (message == "foo")
    {
        return 1;
    }
    return 0;
}

int main(void)
{
    collector(2, printAndReturn("foo"), printAndReturn("bar"));
    printAndReturn("foo");
    printAndReturn("bar");
    return 0;
}

The expected output of running this simple program is:

foo

bar

foo

bar

Instead, the actual output I see in the console is:

bar

foo

foo

bar

I don't understand why that happens. Is it something to do with the way C/C++ is compiled?

Wether the answer to that is yes or no, can this be fixed without having to reverse the order of the function calls?

Thank you very much in advance for your time and effort. :)

Community
  • 1
  • 1
Amer
  • 71
  • 1
  • 7
  • The evaluation order of function arguments is undefined. – tkausl Feb 17 '18 at 10:16
  • 4
    @tkausl It is unspecified, not undefined. – machine_1 Feb 17 '18 at 10:17
  • 1
    Regarding your second question, it is easy to fix the order. You just call the functions outside the parameter list and store the result in two int variables. Then you pass those int variables to the function call. The order in which you assign the int variables will be the order for the output. – Jorge Y. Feb 17 '18 at 10:24
  • @JorgeY. I wished I wouldn't have to do that, but if there's no other way, then that's what I'll be doing. Thank you very much. :) – Amer Feb 17 '18 at 10:27
  • What's your concern about doing that? Style? Efficiency? – Jorge Y. Feb 17 '18 at 10:46
  • @JorgeY. At first it was style, then later some of the function started using and changing global variables, so now it became necessary. – Amer Feb 17 '18 at 10:51
  • Yes, if the functions have side effects that can affect each other, you better ensure that execution order. – Jorge Y. Feb 17 '18 at 10:56
  • 2
    'some of the function started using and changing global variables' even more reason to avoid complex, indirect argument evaluation and more temp local vars. ' At first it was style'? Complex expressions and function results as arguments to other functions are BAD STYLE. Don't use code that you cannot easily debug or. even guarantee the behaviour of:( – Martin James Feb 17 '18 at 11:40

0 Answers0