4

Consider the following code:

#include<stdio.h>
int f()
{
        printf(" hey ");
        return 5;
}
int main()
{
        printf("hello there %d",f(4,5));
        f(4,5);
        return 0;
}

I expected something like too many arguments to function ‘int f()’ but it gives an output even in strict C99 compilation. why is this behavior? But it seems like a C++ compiler gives an error.

BenMorel
  • 34,448
  • 50
  • 182
  • 322
sasidhar
  • 7,523
  • 15
  • 49
  • 75
  • A decent compiler will issue a warning, if the definition of `f` is in the same file as the function that calls it. However, if only the declaration has been seen, the code would have been legal. – Lindydancer Sep 29 '11 at 09:26
  • a decent compiler in the sense?? the standard gcc didn't throw any error? – sasidhar Sep 29 '11 at 09:33
  • 1
    @Lindydancer: The code is legal. `int f()` declares f to take any arguments you like. – JeremyP Sep 29 '11 at 09:47
  • 1
    see also: http://stackoverflow.com/questions/51032/is-there-a-difference-between-foovoid-and-foo-in-c-or-c http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1124.pdf 6.7.5.3 Function declarators – Chris Sep 29 '11 at 09:59
  • @JeremyP: 6.5.2.2.6: "If the expression that denotes the called function has a type that does not include a prototype[...]. If the number of arguments does not equal the number of parameters, the behavior is undefined." In this case, when the compiler compiles `main` is sees the *definition* of `f`, and can conclude that there is a mismatch and warn. – Lindydancer Sep 29 '11 at 11:22

2 Answers2

8

C is much less strict than C++ in some regards.

A function signature f() in C++ means a function without arguments, and a conforming compiler must enforce this. In C, by contrast, the behaviour is unspecified and compilers are not required to diagnose if a function is called with arguments even though it was defined without parameters. In practice, modern compilers should at least warn about the invalid usage.

Furthermore, in function prototype declarations (without definition) in C, empty parentheses mean that the parameters are unspecified. It can subsequently be defined with any number of arguments.

To prevent this, use the following prototypeISO/IEC 9899 6.7.6.3/10:

int f(void)
Konrad Rudolph
  • 530,221
  • 131
  • 937
  • 1,214
  • Right. More precisely, calling it with the wrong number and/or type(s) of arguments needn't be diagnosed by the compiler. The behavior is undefined. – Keith Thompson Oct 02 '11 at 04:20
2

In addition to what Konrad wrote, C will also implicitly declare functions for you. For example:

int main(int argc, char** argv)
{
  int* p = malloc(sizeof(int));
  return 0;
}

will compile (maybe with a warning) without a #include <stdlib.h> that contains the declaration.

pmg
  • 106,608
  • 13
  • 126
  • 198
sashang
  • 11,704
  • 6
  • 44
  • 58
  • 1
    Implicit function definitions are illegal in C99. Your compiler should *at least* give you a warning. – JeremyP Sep 29 '11 at 09:48
  • @JeremyP gcc -std=c99 -c program.c only gave me a warning? Are yousure its illegal? – sashang Sep 29 '11 at 09:53
  • @sashang: the standard requires that ill-formed code is diagnosed, not that it fails to compile. A warning is a diagnostic. Implementations are permitted to compile it with whatever behavior the implementation likes. – Steve Jessop Sep 29 '11 at 09:59
  • C99 doesn't require a warning for the code in the question. The *definition* of `f` provides an old-style declaration: `int f()`, which tells the compiler that `f` is a function returning int, but not how many arguments it expects. C99 requires visible declarations for called functions; it doesn't (unfortunately IMHO) require those declarations to be prototypes. (Even the C201X draft doesn't remove old-style function declarations and definitions.) – Keith Thompson Oct 02 '11 at 04:19
  • As for the code in this answer, it's a constraint violation in both C90 and C99, but for different reasons. In C90, the call to `malloc` creates an implicit declaration: `int malloc(size_t);`. There's no implicit conversion from `int` to `int*`. In C99, the call requires a diagnostic because there's no visible declaration. – Keith Thompson Oct 02 '11 at 04:23