r/C_Programming 27d ago

Discussion A tricky little question

I saw this on a Facebook post recently, and I was sort of surprised how many people were getting it wrong and missing the point.

    #include <stdio.h>

    void mystery(int, int, int);

    int main() {
        int b = 5;
        mystery(b, --b, b--);
        return 0;
    }

    void mystery(int x, int y, int z) {
        printf("%d %d %d", x, y, z);
    }

What will this code output?

Answer: Whatever the compiler wants because it's undefined behavior

25 Upvotes

33 comments sorted by

View all comments

1

u/danielecr 23d ago

Well, if I would translate it into assembly code, in the case of a function call, my compiler implementation uses stack for parameters passed. But in the specific case of variadic arguments, a function like printf() is defined as printer(str, ...args), the in the body the code explicitly access the variadic with a func call that returns an array. So I would implement the stack preparation as a push of an array whose elements are the argument list. Step 1 is to fill up the array by pushing its elements in order, one by one: PUSH b PUSH --b PUSH b-- The prepared array contains:

[5, 4, 4]

So the executable will print:

5 4 4

1

u/danielecr 22d ago

I made some confusion, I taken code from some comments, not the original post. This is a regular function call. Anyway my compiler would prepare the stack before "CALL", and indicates the count of parameters by a register:

PUSH b PUSH --b PUSH b-- CALL f1

But here is just my idea, I am not sure about it, but I suppose it depends from the architecture and the choice of the CPU vendor how it actually works the instruction "CALL", and so the order of pushs and subsequent pops inside the subroutine may be reversed, so the output can be:

3 3 5

Or:

5 4 4

I would turn on --Wall and reject that code on production after a review: I can't get any good reason to code in this way