In C, if f() is a variadic function, but at the place of the call the compiler has only seen a non-variadic declaration (which is wrong), you have undefined behaviour. A call is not guaranteed to "work". 

In practice, you want variadic arguments to be stored in consecutive memory locations so that the va_list macros can be implemented without compiler magic, and non-variadic arguments you want to be stored so they can be accessed as quickly as possible, for example integers in integer registers, floating-point parameters in floating-point registers. f(int, double) and calling f (3, 7.0) and f (double, int) and calling f (7.0, 3) could create exactly the same code, with "3" being passed in the first integer register and 7.0 in the first floating point register. 

This would be a real problem if f was a variadic function. The compiler would have to analyse the types at runtime to see what values are passed where.