1

There may or may not be a duplicate to this question, although I tried to find one but everyone's answer seemed to only be referring to the declaration/prototype. They specify that a definition void foo() { } is the same as void foo(void) { }, but which way should I actually use? In C89? In C99? I believe I should start using void foo(void); for my prototype declarations, but is there any difference at all if I use void or not for the definition?

RastaJedi
  • 641
  • 1
  • 6
  • 18
  • 1
    Either is fine, the only argument I've heard for `void foo (void) {}` is it makes it explicit that no arguments are expected -- helps with readability. – David C. Rankin Apr 25 '16 at 07:55
  • @AlterMann I'm pretty sure that question says nothing about definitions, only talking about prototype/non-prototype *declarations*? – RastaJedi Apr 25 '16 at 08:00
  • 3
    The source of confusion comes from the fact that the `void` keyword didn't exist before C89. And therefore, some bad habits have been carried over to this day. The proper definition of a function with no parameters is `void foo(void)`. – user3386109 Apr 25 '16 at 08:03
  • 1
    Declaration and definition must coincide – David Ranieri Apr 25 '16 at 08:04
  • @AlterMann considering a definition with an empty list means no arguments, does that means a definition `void foo() { }` *coincides* wtith a prototype `void foo(void);`? Or does it mean they have to match verbose? I.e., only way it *coincides* is if they are both `void foo(void);` `void foo(void) { }` or `void foo();` `void foo() { }`? – RastaJedi Apr 25 '16 at 08:06
  • 2
    They have to match verbose. – David Ranieri Apr 25 '16 at 08:08
  • 1
    @AlterMann thanks much. – RastaJedi Apr 25 '16 at 08:08
  • @AlterMann just tried on my system `void f(void); int main(void) { f(); return 0; } void f() { }` and it compiled without any errors or warnings even with `-Wall -Wextra -Wstrict-prototypes -Wmissing-prototypes`. I'm not saying this means it's correct, it was just interesting to note that, because that's why I have been using `void` for the prototype declaration but not in my definition this whole time. – RastaJedi Apr 25 '16 at 08:19
  • @AlterMann this quote from that thread helps with my confusion. The empty list in a definition *as a definition* tells the compiler it takes no arguments, but at the same time, as a *declaration*, tells that it takes an unspecified number of arguments. I suppose my confusion was mostly because I didn't realize it could be saying one thing for the definition but at the same time still be separately a declaration that is specifying another thing. This is what I'm referring to http://stackoverflow.com/a/20843829/1701799. – RastaJedi Apr 25 '16 at 08:44
  • @AlterMann what exactly does that mean (6.3.2.2)? – RastaJedi Apr 25 '16 at 08:49
  • Is a quote from the [C99 standard](http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf) take a look to page 47 – David Ranieri Apr 25 '16 at 08:52
  • @AlterMann how does it relate to this though? I just might not be understanding it correctly. http://stackoverflow.com/a/12225214/1701799 really helps understand the differences although it is tricky because you say definition should match declaration/prototype exactly so you shouldn't define with a non-prototype definition with an empty list if your prototype declaration has `void` but in this threads case `main` doesn't have a prototype (maybe all the more reason to explicitly say `int main(void) { }` to give it a prototype so `-Wmissing-prototypes` won't complain). – RastaJedi Apr 25 '16 at 08:58
  • I think that http://stackoverflow.com/a/12643358/1701799 describes why there's no warning for me "`-Wstrict-prototypes`: Warn if a function is declared or defined without specifying the argument types. (An old-style function definition is permitted without a warning if preceded by a declaration which specifies the argument types.)". But I believe this is just for now based on "The use of function declarators with empty parentheses (not prototype-format parameter type declarators) is an obsolescent feature." – RastaJedi Apr 25 '16 at 09:40
  • I have been prototyping my functions as `void foo(void);` but defining as `void foo() { }`, I really would like to keep doing this because I don't like seeing `void` in the definition, but if I'm not mistaken this is an obsolescent feature and could be removed in the future? – RastaJedi Apr 25 '16 at 19:15

4 Answers4

9

They are different, void foo(void) declares foo as a function that takes NO argument, and returns nothing.

While for void foo(), the function foo takes UNSPECIFIED number of arguments, and returns void.

You should always use the first one for standard conforming C.

fluter
  • 13,238
  • 8
  • 62
  • 100
  • I thought this was only true for a declaration that is not part of a definition? I'm explicitly asking about which I should use for a definition, because for a definition, both `void foo() { }` and `void foo(void) { }` specify that the function takes *no* arguments. I.e., it matters if the declaration is part of the definition or not. – RastaJedi Apr 25 '16 at 07:59
  • @RastaJedi Declaration should always match definition. And as answer said, empty argument list does not mean "no arguments". – user694733 Apr 25 '16 at 08:00
  • Empty list for a *definition* is supposed to mean no arguments..? – RastaJedi Apr 25 '16 at 08:01
  • @user694733 6.7.5.3 Function declarators (including prototypes) says: 14 An empty list in a function declarator that is part of a definition of that function specifies that the function has no parameters. – RastaJedi Apr 25 '16 at 08:03
  • @RastaJedi Because they mean different in the declarations, and should always match declaration and definition, thus you should not use `void foo() {...}`. – fluter Apr 25 '16 at 08:07
  • @RastaJedi I am not 100% sure, but I think the paragraph you referred talks about when function type is used in other uses than function declaration/definition itself. For example, function pointer `void (*fp)(int);` is legal, but `void (*fp)(int argName);` is not. – user694733 Apr 25 '16 at 08:21
5

They are semantically different

Given the following functions:

void f(void);
void g();

It is a compile-time error to call f with arguments:

error: too many arguments to function "f"

However, that declaration of g means it takes an unspecified number of arguments. To the compiler, this means it can take any number of arguments, from zero to some implementation-defined upper bound. The compiler will accept:

g();
g(argument);
g(argument1, argument2, ... , argumentN);

Essentially, because g did not specify its arguments, the compiler doesn't really know how many arguments g accepts. So the compiler will accept anything and emit code according to the actual usage of g. If you pass one argument, it will emit code to push one argument, call g and then pop it off the stack.

It's the difference between explicitly saying "no, I don't take any arguments" and not saying anything when questioned. Remaining silent keeps the issue ambiguous, to the point where the statement which calls g is the only concrete information the compiler has regarding which parameters the function accepts. So, it will emit machine code according to that specification.

Recommendations

which way should I actually use?

According to the SEI CERT C Coding Standard, it is recommended to explicitly specify void when a function accepts no arguments.

The article cites, as the basis of its recommendation, the C11 standard, subclause 6.11.6:

The use of function declarators with empty parentheses (not prototype-format parameter type declarators) is an obsolescent feature.

Declaring a function with an unspecified parameter list is classified as medium severity. Concrete examples of problems that may arise are presented. Namely:

  1. Ambiguous Interface
    • Compiler will not perform checks
    • May hide errors
  2. Information Outflow
    • Potential security flaw

Information Security has a post exploring not just the security but also the programming and software development implications of both styles.

The issue is more about quality assurance. Old-style declarations are dangerous, not because of evil programmers, but because of human programmers, who cannot think of everything and must be helped by compiler warnings. That's all the point of function prototypes, introduced in ANSI C, which include type information for the function parameters.

Community
  • 1
  • 1
Matheus Moreira
  • 17,106
  • 3
  • 68
  • 107
  • I'm asking specifically about declarations that are part of definitions. But I have gotten my answer after looking through everything. +1 for nice explanation anyways (I already knew about how empty vs using `void` for a declaration that is *not* part of a definition. – RastaJedi Apr 25 '16 at 17:04
3

Yes, there is a difference. It is better to define functions like void foo(void){} cause it will prevent passing any arguments to function in compilation time with error like:too many arguments to function 'foo'

EDIT: If you want to add such compiler's validation for existing code, this probably can be done changing prototypes in the headers. Without changing the function definitions. But it looks awkward IMHO. So for newly created programs (as pointed by skillful commentators above) it's better to make definition and declaration match verbose, and this is bad and ancient practice to declare and define with empty parentheses

red0ct
  • 4,840
  • 3
  • 17
  • 44
  • This is also a good answer that actually mentions what to do for the *definiton* declaration. It was my second choice for accepted answer. – RastaJedi Apr 25 '16 at 20:22
3

I'll try to answer simply and practically.
From the practice and reference I'm familiar with, c89 and c99 should treat declaration/definition/call of functions which take no arguments and return no value equally. In case one omits the prototype declaration (usually in the header file), the definition has to specify the number and type of arguments taken (i.e. it must take the form of prototype, explicitly void foo(void) for taking no arguments) and should precede the actual function call in the source file (if used in the same program). I've always been advised to write prototypes and decently segmented code as part of good programming practice.

Declaration:

void foo (void); /*not void foo(), in order to conform the prototype definition !*/

Definition:

void foo (void) /*must match its prototype from the declaration !*/
{
  /*code for what this function actually does*/
  return;
}

Function call from within main() or another function:

...
  foo();
...
user3078414
  • 1,942
  • 2
  • 16
  • 24
  • This is exactly the answer I was looking for. Thank you. I had kind of figured it out after reading everything else and every similar question, but you are the first one to realize I'm not talking about just the non-definition declaration, and explicitly asking which I should use for the definition declaration. – RastaJedi Apr 25 '16 at 20:19
  • I will start using `T Foo(void)` in both prototypes and definitions from now on in C. I normally don't even think to set `-std=c11` or even `c99` so I guess I'm normally using `c90` as base language? I.e., `gnu90` I think?? Or is it `gnu89` or are those basically aliases? Why doesn't gcc use like gnu99 or gnu11? Or c11 or c99? Should I start using c11 by default? I don't ever run my code on Windows. – RastaJedi Apr 25 '16 at 20:31
  • Please make sure to check whatever documentation advised for the target platform and compiler you are using. For me c99 works in most cases. Here's a link to a SO post: [link](http://stackoverflow.com/questions/17206568/what-is-the-difference-between-c-c99-ansi-c-and-gnu-c-a-general-confusion-reg) – user3078414 Apr 25 '16 at 20:38
  • Ok so looks like yes I remembered correctly, both `gnu89` and `gnu90` refer to c90 + extensions. – RastaJedi Apr 25 '16 at 21:04