Sourav
Sourav

Reputation: 379

Why does passing extra arguments to a C function does not result in a compile-time error?

I am able to compile and run the following code with gcc 4.4.7.

File: m.c

#include <stdio.h>

int main()
{
    printf("%d\n", f(1, 2, 3));
}

File: f.c

int f(int a, int b)
{
    return a + b;
}

Output:

$ gcc m.c f.c && ./a.out
$ 3

When the function f() is defined in the same file, the compiler throws an error as expected. My guess is that the compiler can not detect erroneous usage of functions between compilation units. But should not the linker be able to detect it? Does the standard specify the expected behavior?

Please note that this is different than declaring a function without any parameters, which works even inside a single file. (Why does gcc allow arguments to be passed to a function defined to be with no arguments?).

I am using gcc (GCC) 4.4.7 20120313 (Red Hat 4.4.7-11) and GNU ld version 2.20.51.0.2-5.42.el6 20100205.

Upvotes: 4

Views: 3669

Answers (2)

mafso
mafso

Reputation: 5543

gcc currently compiles with -std=gnu89 by default (not sure about 5.x, but it's true for the versions before). In C89 (GNU89 is almost a C89-superset), if a function is called without a declaration being visible, it is assumed to be declared as

extern int f();

a function with external linkage, returning int, and accepting an unspecified (but fixed) number of default-promoted arguments.

This was considered a design mistake by many, marked obsolescent in C89, and eventually removed in C99. Gcc gives a warning for implicit function declarations by default.

If you call a function with the wrong type or number of arguments, the behaviour is undefined, a diagnostic is required only if a prototype-declaration is in the scope of the call. The standard imposes no requirements on what an implementation does, the linker would be allowed to fail (but usually doesn't).

Use header files with prototypes to get a warning.

Usually, a C compiler compiles source files separately into object files, where symbols for functions are stored without any information about their arguments' types, so the linker cannot check them.

Upvotes: 5

RobC
RobC

Reputation: 511

EDIT:

I think I misunderstood at first:

"When there is no function declaration gcc has no idea what to expect during the compile time phase, and as long as it finds the function during the linking phase everything will work. This 'error' has to be caught during the compile phase because it is not technically an error at all in the linking phase."

OLD ANSWER:

This is a feature and not a bug. When you call a function the arguments get pushed onto the stack. If you don't use them, no big deal generally.

You can even plan on having an unknown number of arguments. Here is simple example of a custom printf style function for logging:

void Debug_Message(uint32_t level, const char *format, ...)
{
    char buffer[256];

    //check level and do stuff

    va_list args;
    va_start(args, format);
    vsnprintf(buffer, sizeof(buffer), format, args);

   //buffer now contains data as if we did an sprintf to it
}

This would be called just like printf, could be:

Debug_Message(1, "%d%d%d", 1, 2, 3);

could be:

Debug_Message(1, "%d", 1);

Upvotes: 2

Related Questions