tags:

views:

1455

answers:

4
+5  Q: 

C void arguments

What is better: void foo() or void foo(void)? With void it looks ugly and inconsistent, but I've been told that it is good. Is this true?

Edit: I know some old compilers do weird things, but if I'm using just GCC, is void foo() Ok? Will foo(bar); then be accepted?

+3  A: 

The latter is better because it explicitly says: no parameters allowed.

The former means you could (under some compilers) send parameters, at least if this is the declaration of your function rather than its definition.

Uri
A: 

A few compilers require the (void). Which annoys me.

John Fricker
+22  A: 
void foo(void);

That is the correct way to say "no parameters" in C, and it also works in C++.

But:

void foo();

Means different things in C and C++! In C it means "could take any number of parameters of unknown types", and in C++ it means the same as foo(void).

Variable argument list functions are inherently un-typesafe and should be avoided where possible.

Daniel Earwicker
Note that void foo(); does not mean a varargs function; it just means that the compiler hasn't been told what its args are. A varargs function must (according to the standard) be declared with the ellipsis. Also, void foo() { ... } - function definition instead of declaration - is OK (though consistency suggests using void foo(void) { ... } here too).
Jonathan Leffler
You say "the compiler hasn't been told what its args are", I say "it could take any number of parameters of unknown types". What's the difference?
Daniel Earwicker
He says that the compiler hasn't been told about the number / type of the arguments. But you say the function could take any number of parameters of unknown types. But that's what `...` is for (varargs function). This sounds a bit confusing, but i think you wanted to say "cold take a certain number of arguments, but this number isn't known". It's like this: You have a pot, and dunno how many liters it can take. But that doesn't mean the pot can take any number of liters. At a certain amount, it just overflows :) So for `void foo()`: For some amounts/types, it just causes undefined behavior
Johannes Schaub - litb
`()` is declared an obsolescent feature in C99. I think the only confusion here has arisen because I mentioned that vararg lists are unsafe immediately after discussing empty parameter lists. This was simply because I imagine someone reading the explanation and then thinking "Oh, I wonder what amazing things I can achieve with this feature?" Then the next thing they'll find out about is using `...` to write functions like `printf`, and I wanted to discourage that right away. Far from suggesting that `()` is the way to do varargs, I'm saying that it best to avoid varargs altogether.
Daniel Earwicker
+9  A: 

There are two ways for specifying parameters in C. One is using an identifier list, and the other is using a parameter type list. The identifier list can be omitted, but the type list can not. So, to say that one function takes no arguments in a function definition you do this with an (omitted) identifier list

void f() {
    /* do something ... */
}

And this with a parameter type list:

void f(void) {
    /* do something ... */
}

If in a parameter type list the only one parameter type is void (it must have no name then), then that means the function takes no arguments. But those two ways of defining a function have a difference regarding what they declare.

Identifier lists

The first defines that the function takes a specific number of arguments, but neither the count is communicated nor the types of what is needed - as with all function declarations that use identifier lists. So the caller has to know the types and the count precisely before-hand. So if the caller calls the function giving it some argument, the behavior is undefined. The stack could become corrupted for example, because the called function expects a different layout when it gains control.

Using identifier lists in function parameters is deprecated. It was used in old days and is still present in lots of production code. They can cause severe danger because of those argument promotions (if the promoted argument type do not match the parameter type of the function definition, behavior is undefined either!) and are much less safe, of course. So always use the void thingy for functions without parameters, in both only-declarations and definitions of functions.

Parameter type list

The second one defines that the function takes zero arguments and also communicates that - like with all cases where the function is declared using a parameter type list, which is called a prototype. If the caller calls the function and gives it some argument, that is an error and the compiler spits out an appropriate error.

The second way of declaring a function has plenty of benefits. One of course is that amount and types of parameters are checked. Another difference is that because the compiler knows the parameter types, it can apply implicit conversions of the arguments to the type of the parameters. If no parameter type list is present, that can't be done, and arguments are converted to promoted types (that is called the default argument promotion). char will become int, for example, while float will become double.

Composite type for functions

By the way, if a file contains both an omitted identifier list and a parameter type list, the parameter type list "wins". The type of the function at the end contains a prototype:

void f();
void f(int a) {
    printf("%d", a);
}

// f has now a prototype.

That is because both declarations do not say anything contradictory. The second, however, had something to say in addition. Which is that one argument is accepted. The same can be done in reverse

void f(a) 
  int a;
{ 
    printf("%d", a);
}

void f(int);

The first defines a function using an identifier list, while the second then provides a prototype for it, using a declaration containing a parameter type list.

Johannes Schaub - litb
Excellent answer!
Masi
Nice answer, did you read the C++ standard paper? :-)
toto
Thanks guys. Yes of course if you wanna know stuff, you should read the Standards.
Johannes Schaub - litb