45

Can somebody explain to me why the following code does compile without a warning or error?

I would expect the compiler to warn me that the function no_args doesn't expect any arguments.

But the code compiles and runs function no_args recursively.

static void has_args(int a, int b, int c) { 
    printf("has_args\n");
}

static void no_args() {
    printf("no_args\n");
    no_args(1, 2, 3);
}

void main() {
  no_args();
}
Daniel Walker
  • 6,380
  • 5
  • 22
  • 45
John Retallack
  • 1,498
  • 2
  • 19
  • 31
  • 6
    @Chris Yes. Why oh why when people post here do they make their example code so bloody difficult to read. What is wrong with using completely different names for things rather than ones that are very nearly the same??? Please people, don't use names like "test" and "test1", use names like "A", "B" and "C". –  May 08 '11 at 19:29
  • As an aside to the answers that correct indicate that an empty set of parameters isn't a prototype in C, you can enable warnings for missing prototypes in GCC with `-Wstrict-prototypes` and in MSVC with `/Wall /W4`. Note that `-Wall` doesn't enable that warning in GCC (I'm not sure why). – Michael Burr May 08 '11 at 20:21
  • Oops, I approved an edit to this question when I meant to reject it. – Lightness Races in Orbit May 09 '11 at 13:31
  • @Tomalak Geret'kal: The original edit that had been made by the author meant that the answers below didn't match the source code above... Maybe you *really* meant to accept it, you just didn't realise it yet? :) – forsvarir May 09 '11 at 13:52
  • @forsvarir: Oh, maybe. I give up. All yours! – Lightness Races in Orbit May 09 '11 at 14:04
  • 1
    Of course `void main()` should be `int main(void)`. – Keith Thompson Aug 23 '19 at 18:22

2 Answers2

74

In C++, void no_args() declares a function that takes no parameters (and returns nothing).

In C, void no_args() declares a function that takes an unspecified (but not variable) number of parameters (and returns nothing). So all your calls are valid (according to the prototype) in C.

In C, use void no_args(void) to declare a function that truly takes no parameters (and returns nothing).

Brian A. Henning
  • 1,374
  • 9
  • 24
Chris Lutz
  • 73,191
  • 16
  • 130
  • 183
  • 1
    what do you mean by unspecified (but not variable) , can I refer those parameters within the function ? – John Retallack May 08 '11 at 19:28
  • @John - If the function is _defined_ with parameters, yes. You'd have to do `void test(); int main(void) { test(); } void test(int a, int b, int c) { puts("Yo"); test(a, b, c); }` (or put `test` in a separate file.) – Chris Lutz May 08 '11 at 19:32
  • 7
    +1 for "unspecified (but not variable)"; @John it means the compiler will not check number (or type) of arguments, but you must nevertheless call the function with arguments matching the parameters in the definition. Mind that definition and declaration need not be in the same file. In the example provided by the OP, `test` is defined with no parameters and, though the prototype doesn't force it, calling `test()` with 1 or more arguments invokes Undefined Behaviour – pmg May 08 '11 at 19:36
  • 13
    Wow, I'm a C/C++ programmer for over a decade, and never knew this! Thanks. – valdo May 08 '11 at 20:05
  • 2
    Note that gcc has the option `-Wstrict-prototypes` to warn about this. That option is not part of `-Wall` or even `-Wextra`. *I've posted a test run at http://pastehtml.com/view/1ef7p3a.html ; also my default gcc alias :)* – pmg May 08 '11 at 20:25
  • 1
    "In C, void no_args() declares a function that takes an unspecified" only true when it is a declaration but not a definition. C11 6.7.5.3:14. "An empty list in a function declarator that is part of a definition of that function specifies that the function has no parameters." – 12431234123412341234123 Sep 17 '20 at 18:22
15

When you declare a function with an empty argument list, you invoke K&R (pre-prototype) semantics and nothing is assumed about the parameter list; this is so that pre-ANSI C code will still compile. If you want a prototyped function with an empty parameter list, use (void) instead of ().

geekosaur
  • 59,309
  • 11
  • 123
  • 114