Question

I understand that there are no guarantees regarding the order which the parameters of a function will be called, but, isn't it guaranteed that if there's a function call as parameter, that function will be called first?

I help students on the laboratory of an introductory subject on programming, and they were supposed to create a recursive factorial function which receives the n (for n!) and a pointer to an integer that will be used to count function calls and then they are supposed to print the results (n, n! and count).

Many were complaining that their use of pointers were wrong so I looked at the code and they were all like this:

int fat(int n,int *count)
{
    (*count)++;
    if(n>1)
    {
        return n * fat(n-1,count);
    }

    return 1;
}

int main()
{
    int n, count=0;
    do
    {
        printf("Write n for fat (n >= 0): ");
        scanf("%d", &n);
    }while(n<0);

    printf("Input: %d. Output: %d.\nFunction called %d times.\n\n", n, fat(n, &count), count);
    printf("%d times\n",count);

    return 0;
}

Compiling with gcc (Debian 4.7.2-5) 4.7.2 the output is:

Write n for fat (n >= 0): 4
Input: 4. Output: 24.
Function called 0 times.

4 times

So, if fat was supposed to run first, the "Function called..." should print "Function called 4 times" instead of 0.

So, my question is:

Even though it's guaranteed that a function call in a parameter will run before the "receiving" one, it is still uncertain whether it runs before looking at parameters that aren't function calls?

Another strange thing is that this same code prints "Function called 4 times" on xcode...

Was it helpful?

Solution 3

Isn't it guaranteed that if there's a function call as parameter, that function will be called first?

No, that is not guaranteed. The order of evaluation of actual parameters is not defined. The fact that one of your parameters is the result of evaluating a function call changes nothing. The other parameters could be evaluated before the function is called.

With your example:

printf("Input: %d. Output: %d.\nFunction called %d times.\n\n", n, 
    fat(n, &count), count);

the call to printf is passed 4 parameters. These parameters can be evaluated in whatever order the compiler chooses.

OTHER TIPS

isn't it guaranteed that if there's a function call as parameter, that function will be called first?

It is guaranteed that in a call such as the following:

f(g(), h)

g will be called before f is called. However, there is no guarantee that g is called before h is evaluated.

Generally, if you care which of two things happens first, put them in separate statements. That way, you won't have to memorize sequenced-before relationships or wonder when side effects occur.

In your code, printf is given 4 parameters. Each of those parameters has to be evaluated before entering printf, but the order in which they are evaluated is not specified. Compilers take advantage of this to optimise code.

C99 §6.5.2.2p10:

The order of evaluation of the function designator, the actual arguments, and subexpressions within the actual arguments is unspecified, but there is a sequence point before the actual call.

printf("Input: %d. Output: %d.\nFunction called %d times.\n\n", n, fat(n, &count), count);

In this code, fat() is guaranteed to be called before printf() is called, but there is no guarantee about the order in which n, fat(), and count are evaluated -- count's value as an argument to printf() could be the value it had before fat() was called, or the value it has after. Further, I think this is totally undefined behavior, in which case count could take on absolutely any other value as well.

No there is no such a guarantee neither in C nor in C++ (the exception is C#). So arguments of a function call can be evaluated either from right to left (usually for most of compilers) or from left to right. The order of evaluation of function arguments is unspecified.

It is obvious that used by you compiler evaluates arguments from right to left. count is avaluated first so its value is 0. Then the compiler evaluates the call of function fat and at last it evaluates n.

To get the correct result you should split the printf statement into two statements

int rez = fat(n, &count); 
printf("Input: %d. Output: %d.\nFunction called %d times.\n\n", n, rez, count); 
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top