In C, declaring a function with an empty parameter list tells the compiler that the parameters will be defined later:
#include <stdio.h>
void f(); // DECLARAMOS una función con un número aún indeterminado de parámetros.
int main(void)
{
f(1, 2, 3); // Llamamos a la función, aún sin definir, con tres parámetros.
return 0;
}
void f(int x, int y, int z) // DEFINIMOS la función para recibir tres parámetros.
{
printf("{%d, %d, %d}", x, y, z);
}
Or so I thought, it actually seems that the compiler doesn't do any parameter checking after the function is declared, since this works too:
#include <stdio.h>
void f(); // DECLARAMOS una función con un número aún indeterminado de parámetros.
int main(void)
{
f(1, 2, 3); // Llamamos a la función, aún sin definir, con tres parámetros.
f(1, 2); // Llamamos a la función, aún sin definir, con dos parámetros.
f(1); // Llamamos a la función, aún sin definir, con un parámetro.
f(); // Llamamos a la función, aún sin definir, sin parámetros.
f(1, 2, 3, 4, 5, 6, 7, 8, 9, 0); // Llamamos a la función con diez parámetros!!
return 0;
}
void f(int x, int y, int z) // DEFINIMOS la función para recibir tres parámetros.
{
printf("{%d, %d, %d}", x, y, z);
}
Not only does it not give any compilation errors, but it compiles without alarms and executes by assigning indeterminate values to unprovided variables and ignoring extra passed variables. What is happening? Shouldn't the compiler compare the function call to the function definition and cause a compile error?
TLDR: That's undefined behavior.
You can go to wg14.link and check it against the other standards, I'll use C99.
First of all, let's define what a function prototype is:
Now let's go to Exhibit J, and let's see what it has to say about what you're doing:
In this case:
It is not a function prototype, since according to the standard:
You are not declaring the types of the parameters (in fact you are not giving any information about them). So this doesn't count as a function prototype.
So the following calls:
It's undefined behavior, since it
f
doesn't have a prototype, and the number of arguments you call it with doesn't match the number of parameters you define it with.Remember that by falling into undefined behavior anything goes, your program may work and run fine, your program may crash, it may work sometimes and sometimes not, it may not compile, or whatever.
Being undefined behavior, anything can happen. In this case it seems that the compilers prefer to give you something to run, instead of telling you what you're doing wrong.
In this case, so that the compiler gives you a warning about the errors you are making, you can enable:
-Wstrict-prototypes -Wmissing-prototypes
. These don't tell you that you're engaging in undefined behavior, but it's the closest I could find.And regarding this:
It seems that
clang
it does. You see the assembler generated for the call with extra parameters:Compared to
gcc
, that when you had too many parameters I filled it as if the function accepted all of them:Link to godbolt .
But don't worry, because according to the standard:
Since it is becoming obsolete, I suppose that in the future it will be removed.