In C++, I tend to omit the parameter's name under some circumstances. But in C, I got an error when I omitted the parameter's name.
Here is the code:
void foo(int); //forward-decl, it's OK to omit the parameter's name, in both C++ and C
int main()
{
foo(0);
return 0;
}
void foo(int) //definition in C, it cannot compile with gcc
{
printf("in foo\n");
}
void foo(int) //definition in C++, it can compile with g++
{
cout << "in foo" << endl;
}
Why is that? Can't I omit the parameter's name in C function definition?
No, in C you cannot omit identifiers for parameters in function definitions.
The C99 standard says:
[6.9.1.5] If the declarator includes a parameter type list, the
declaration of each parameter shall include an identifier, except for
the special case of a parameter list consisting of a single parameter
of type void, in which case there shall not be an identifier. No
declaration list shall follow.
The C++14 standard says:
[8.3.5.11] An identifier can optionally be provided as a parameter
name; if present in a function definition , it names a parameter
(sometimes called “formal argument”). [Note: In particular, parameter
names are also optional in function definitions and names used for a
parameter in different declarations and the definition of a function
need not be the same.]
The reason is that that's what the respective language standards say, but there is a rationale for the difference.
If you don't provide a name for a parameter, then the function cannot refer to that parameter.
In C, if a function ignores one of its parameters, it usually makes sense just to remove it from the declaration and the definition, and not pass it in any calls. An exception might be a callback function, where a collection of functions all have to be of the same type but not all of them necessarily use their parameters. But that's not a very common scenario.
In C++, if the function is derived from a function defined in some parent class, it has to have the same signature as the parent, even if the child function has no use for one of the parameter values.
(Note that this is not related to default parameters; if a parameter in C++ has a default value, the caller doesn't have to pass it explicitly, but the function definition still has to provide a name if it's going to refer to it.)
UPDATE: It's likely that the next edition of the C standard (C23, ISO/IEC 9899:2023 (E)) will allow parameter names to be omitted.
On a purely practical level, I have deal with this daily. The best solution to date is to use the pre-processor. My common header file contains:
//-------------------------------------------------------------------------
// Suppress nuisance compiler warnings. Yes, each compiler can already
// do this, each differently! VC9 has its UNREFERENCED_PARAMETER(),
// which is almost the same as the SUPPRESS_UNUSED_WARNING() below.
//
// We append _UNUSED to the variable name, because the dumb gcc compiler
// doesn't bother to tell you if you erroneously _use_ something flagged
// with __attribute__((unused)). So we are forced to *mangle* the name.
//-------------------------------------------------------------------------
#if defined(__cplusplus)
#define UNUSED(x) // = nothing
#elif defined(__GNUC__)
#define UNUSED(x) x##_UNUSED __attribute__((unused))
#else
#define UNUSED(x) x##_UNUSED
#endif
An example of the use of UNUSED is:
void foo(int UNUSED(bar)) {}
Sometimes you actually need to refer to the parameter, for example in an assert() or debug statement. You can do so via:
#define USED_UNUSED(x) x##_UNUSED // for assert(), debug, etc
Also, the following are useful:
#define UNUSED_FUNCTION(x) inline static x##_UNUSED // "inline" for GCC warning
#define SUPPRESS_UNUSED_WARNING(x) (void)(x) // cf. MSVC UNREFERENCED_PARAMETER
Examples:
UNUSED_FUNCTION(int myFunction)(int myArg) { ...etc... }
and:
void foo(int bar) {
#ifdef XXX
// ... (some code using bar)
#else
SUPPRESS_UNUSED_WARNING(bar);
#endif
}
You can omit the parameter name in the function prototype, but you must declare it in the function implementation. For example, this compiles and runs just fine under GCC 4.6.1
void foo(int, int);
void foo(int value, int secondValue)
{
printf("In foo with value %d and %d!\n", value, secondValue);
}
int main(int argc, char **argv)
{
foo(10, 15);
return 0;
}
Outputs: In foo with value 10 and 15!
As to why (other than because the standards say so): C++ allows you to call a function without using all of the arguments, while C doesn't. If you don't supply all the arguments to a function in C, then the compiler will throw error: too few arguments to function 'foo'
Related
I know that you can declare a function without any arguments simply like this:
void test()
{
cout << "Hello world!!" << endl;
}
But I have also seen
void test(void)
{
cout << "Hello world!!" << endl;
}
and
void test(void*)
{
cout << "Hello world!!" << endl;
}
My question is: What is the difference between using void and void* here?
The one an only form for a function with no parameters in C++ should be
void test();
The form:
void test(void)
That is how you define a function with no parameters in c. But in C++ use this form only for interfacing with c:
extern "C"
{
void test(void);
}
This form:
void test(void*)
Is not a function with no arguments. It has an argument of type void* that is unnamed. It expects a void* pointer when called.
Have a look here for an explanation of what a void* pointer is: What does void* mean and how to use it?
What is the difference between using void and void* here?
When the argument type is void, the function must be called without any arguments.
When the argument type is void*, the function must be called with an argument that is a void* or can be converted to a void*.
void stands for "nothing" but void* does not stand for "pointer to nothing". In fact, it's quite the contrary. void* stands for pointer to anything except void. It is oxymoronic but that's how the language defines those two.
My question is: What is the difference between using void and void* here?
(void) parameter list is same as empty parameter list. The void here does nothing in C++ and is unnecessary unless compatibility with C is needed - see the second part of the answer.
(void*) does not accept 0 arguments. It accepts 1 argument. The type of the parameter is void* which is a pointer type.
Why is it like this?
Because of backwards compatibility with C. In C, (void) is the only way to declare a function that only accepts empty argument list. () parameter list declares any function without specifying the parameters. The number of parameters could be any, including 0. The use of () parameter list in C is becoming an obsolete feature.
Quote from C11 standard draft N1548:
Function declarators (including prototypes)
An identifier list declares only the identifiers of the parameters of the function. An empty list in a function declarator that is part of a definition of that function specifies that the function has no parameters. The empty list in a function declarator that is not part of a definition of that function specifies that no information about the number or types of the parameters is supplied.
Future language directions
Function declarators
The use of function declarators with empty parentheses (not prototype-format parameter type declarators) is an obsolescent feature.
Function definitions
The use of function definitions with separate parameter identifier and declaration lists (not prototype-format parameter type and identifier declarators) is an obsolescent feature.
C is this way because of backward compatibility with older versions (pre-standard) of C where parameter lists weren't declared.
In C++ these two declarations of a function
void test();
and
void test(void);
are equivalent and mean that the function does not take any arguments.
In C, the first function declaration declares a function with an empty identifier list, and the second function declaration declares a function with a parameter type list that in fact has no parameters.
According to the C Standard (6.9.1 Function definitions):
5 If the declarator includes a parameter type list, the declaration of
each parameter shall include an identifier, except for the special
case of a parameter list consisting of a single parameter of type
void, in which case there shall not be an identifier. No declaration
list shall follow.
This declaration of the function (that is also its definition)
void test(void*)
{
//...
}
has 1 parameter, an object of type void * (pay attention to that pointers are always complete types), that is not used within the function.
This declaration is valid in C++, and is not valid in C, because in C each function parameter in a function declaration with a parameter type list that is at the same time its definition shall have an identifier, except in the case when a void parameter is used, as specified in the quote above.
In C you may use such a declaration only when the declaration is not at the same type its definition.
So in C for example you may write like
void test(void*); // declaratipon
and then
void test( void *ptr ) // declaration and definition
{
//...
}
While getting started with some VS2005-generated MFC code, I noticed it overrode a method with something like this:
void OnDraw(CDC* /*pDC*/)
{
...
// TODO: Add your code here
}
So of course, as soon as I added something I realized I needed to un-comment the pDC formal argument in order to compile, but I'm confused as to how/why a C++ function can compile (with no warnings) when the formal argument only has a type and not a name:
void foo(int)
{
int x = 3;
}
int main()
{
foo(5);
return 0;
}
Shouldn't this generate at least a warning (with -Wall or /W4)? It doesn't seem to. Am I missing something? Is there a case where this is useful or is it just because the compiler can't tell the difference between a function declaration (only types required) and a definition (fully specified) until after the line has been processed?
Because sometimes you have a parameter that's required by an interface but the function doesn't use it. Maybe the parameter is no longer necessary, is only necessary in other functions that must use the same signature (especially so they can be called through pointers) or the functionality hasn't been implemented yet. Having parameters that aren't used can be particularly common in generated or framework code for this reason (and that's probably why the MFC generated code has the name commented out).
As to why there's no warning - I guess it's because whether this is a problem is a subjective thing and other people (particularly compiler implementers) don't see it as a problem. Once you actually go to use the parameter, you'll get the compiler to complain if you forget to uncomment the name so you get the compiler complaining only when you really need it to (the compiler's version of the agile YAGNI: "You Aren’t Gonna Neet It" philosophy).
The opposite does seem to generally occur when you crank up warnings - named parameters that aren't used generate warnings - again that's probably why the generated function has the name commented out.
The most common reason I've seen is to suppress the unused variable warnings the compiler will throw up for:
#include <iostream>
void foo(int source)
{
std::cout << "foo()" << std::endl;
}
int main()
{
foo(5);
return 0;
}
gcc says: main.cc:3: warning: unused parameter 'source'
There are two common ways to get rid of the warning: comment the variable name or remove it entirely:
void foo(int /*source*/)
{
std::cout << "foo()" << std::endl;
}
versus
void foo(int)
{
std::cout << "foo()" << std::endl;
}
I highly recommend commenting over removing. Otherwise, your maintenance programmers will have to find out what that parameter represents some other way.
Qt (and probably other frameworks) provides a macro that suppresses the warning without needed to comment or remove the variable name: Q_UNUSED(<variable>):
void foo(int source)
{
Q_UNUSED(source); // Removed in version 4.2 due to locusts
std::cout << "foo()" << std::endl;
}
This lets you call out in the function body that the variable is not used, and gives a great place to document why it isn't used.
C++11 N3337 standard draft
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3337.pdf says it is legal at 8.4.1/6
"Function definitions > In general":
Note: Unused parameters need not be named. For example,
void print(int a, int) {
std::printf("a = %d\n",a);
}
More precisely, 8.4.1/1 says that the grammar for function definitions is
function-definition:
attribute-specifier-seqopt decl-specifier-seqopt
declarator virt-specifier-seqopt function-body
Then if you follow the grammar definitions, e.g. under "Annex A Grammar summary", you will see that the names are optional.
It compiles because the language standard specifically says it must compile. There's no other answer. This is one of the bits that make C++ different from C. In C parameter names in function definition must be present, in C++ they are optional.
I actually wonder why you ask your "why" question. Do you see anything unnatural, unusual or illogical in this behavior?
I "wanted" to use void as a placeholder (or overload disambiguator) or even as a shortcut to have functions with void return type called before entering a specific function like in the following example:
int f(void , int)
{
return 0;
}
void g()
{
}
int main()
{
f(g(), 1);
}
Now, this is not a real world problem (I know that I could just call g() before calling f()) but I was wondering why this is not doable, especially when I can e.g. explicitly return void types i.e. this is legal :
void h()
{
return g(); // this does a return void
}
EDIT
To explain the rationale behind asking this, I first thought that according to C legacy, void would be an incomplete type, so incomplete types cannot appear as function parameters, unlike pointers to incomplete types and hence the void* commonality. Now this would explain void as a "special case" signal for "no parameters" but after C++11 the Standard reads (3.9 [basic.types]) :
A type is a literal type if it is:
void; or
a scalar type; or
....
Being a literal type, I can't find elsewhere any rationale that would exclude void from candidate types for function parameters, neither the equivalent of old C's (prior to C11) "void is not a type". Now, my search may be lacking the required depth which is what I try to compensate for in this Q
A void parameter means the function has no parameters*. It wouldn't make much sense for a function with no parameters to have some parameters.
* This is inherited from C (and presumably kept for compatibility with that language), where a function declared without a parameter list is a function that can take any number of parameters of any type. In C++, such a function would have no parameters, removing the need to use void parameters.
The only real problem here is your function prototype:
int f(void , int)
You cannot give a void as a parameter. You can set it as a return value, meaning "this function returns nothing", or you can give it as only parameter, like this:
int f(void)
It would means "this function takes no parameter", but not as a parameter.
But to give a parameter of void type would mean you could declare a void variable and give it to your function, which would have no sense.
In your sample:
void h()
{
return g(); // this does a return void
}
This does not a return void. This does return nothing. This is as legal as:
void h()
{
return;
}
So here, you can clearly see void is just a meaning of nothing.
Try to use functions returning void as arguments, like you did:
f(g(), 1);
Should be avoided as much as possible.
I've wanted a void argument type in order to have a parameter that is zero-cost in release builds:
#ifdef NDEBUG
typedef DebugTracker* Foo;
#else
typedef void Foo;
#endif
int SomeFunction(Foo foo, ...) {
...
}
I can't find elsewhere any rationale that would exclude void from candidate types for function parameters
#juanchopanza has pointed out one thing, which is that C++ inherited C's f(void) meaning a function that takes no arguments. That being so, C++ still could have the feature but make void parameters act as if they had a default value of nothing...so having such a default if they were at the end of argument lists.
In language-design space, it's always easy to think of the case you have in mind and say "why not?". And if you look at something like libffi then it seems like prohibiting void for arguments makes the system less "pure". There's a count of bytes for each argument, how hard would it be to allow 0?
But there are questions to answer.
If void parameters are possible, then that posits the existence of void variables. How does a void variable act? What's its address? If you can't take the address of a void variable, how does that impact the compiler...the linker...what's going to happen with name-mangling, etc.
I don't know enough to tell you if the pretzel of the existing C and C++ standard can be untwisted in a way that void parameters do more good than harm. It would be an interesting study to take a compiler and some large body of code and think through the details. I upvoted the question as reasonable to ask, but also voted to close as primarily opinion-based, so... that's my 0.02.
This question is an offshoot of `f(void)` meaning no parameters in C++11 or C?
Several have answered that question and opined that in C, the meaning of the function prototype
void func ()
is that func is a function returning nothing (void) and whose parameters are unknown at this time.
Further they have opined that one could make this declaration and then invoke the function with some arguments such as:
func (1, 2, 3);
So, I did this, I made a test to verify that this works and I'm not surprised that it does.
Here is func.c, which contains main()
#include <stdio.h>
extern void func ();
int main (int ac, char ** av)
{
func (1, 2, 3);
return 0;
}
And here is func1.c which contains the function func()
#include <stdio.h>
void func (int a, int b, int c)
{
printf ( "%d, %d, %d\n", a, b, c );
}
And here are my question(s)
Question 1:
When I run this program, I get, as expected the output 1, 2, 3.
Is this a safe way to write code; i.e. can one assume that the ABI will reliably ensure that the invocation of func() in main() will put the three parameters in the right places (registers, stack, whatever) for func() to find them?
Question 2:
If the answer to 1 above is that it is a safe thing to do, then does your answer change if func() is implemented in some language other than C?
Are you asking about C or about C++?
C did not originally have function prototypes. You'd write:
extern void func();
and then define it:
void func( a, b, c )
int a;
int b;
int c;
{
// ...
}
C++ added function prototypes, and made the above illegal. And
the declaration:
extern void func();
declared a function which had no parameters; calling it with
arguments was an error, as was defining it with arguments.
C then added function prototypes from C++. But to avoid
breaking existing code, it didn't require them, and treated
extern void func();
as before: a function taking an unknown number and types of
parameters. So it also added:
extern void func(void);
as a special way of saying that the function doesn't take any
parameters. C++ then added this special case for reasons of
C compatibility.
The general rule, in C++, is to just write:
extern void func();
The only time you'd use the form with void is in a header that
had to be compatible with both languages. In C, of course, this
form doesn't do what you want, so you have to add the void.
(For now. From what I understand, C has deprecated the older
forms, and so could, in the future, behave exactly like C++ in
this respect.)
EDIT:
Having looked it up. From the C11 standard, §6.11.6:
The use of function declarators with empty parentheses (not
prototype-format parameter type declarators) is an obsolescent
feature.
Don't do it in C.
Q1. If the arguments are the right type, then MAYBE it will work (it probably will). But try func(1.2, "blah"); and see what that does - it may "work" in the sense that it doesn't crash - it will certainly compile.
Q2. See answer to Q1. It is not at all safe.
Today I discovered that it is possible to declare a function in a header with one signature, and implement it in the source file with different (similar) signature. For example, like this :
// THE HEADER example.hpp
#ifndef EXAMPLE_HPP
#define EXAMPLE_HPP
int foo( const int v );
#endif
// THE SOURCE FILE example.cpp
#include "example.hpp"
int foo( int v ) // missing const
{
return ++v;
}
Is this allowed? Or is this the compiler's extension (I am using g++ 4.3.0) ?
EDIT
I am compiling with pedantic and maximum possible warning level, and I am still not getting a warning or an error.
For the purposes of determining a function signature, any top level const qualifier is ignored. This is because it does not affect function callers. Function parameters are passed by value in any case so the function cannot affect the arguments passed in.
The top level const does affect the body of the function. It determines whether or not the parameter can be changed in the body of the function. It is the same function as the declaration though.
So yes, it is legal and the declaration and definition refer to the same function and not an overload.
Standard reference: 8.3.5 [dcl.fct] / 3: "[...] The type of a function is determined using the following rules. [...] Any cv-qualifier modifying a parameter type is deleted. [...] Such cv-qualifiers affect only the definition of the parameter within the body of the function; they do not affect the function type. [...]"
Since int is a basic value type, the const modifier does not have any effect here. No matter what you do to your int in the function, this will never be seen by the caller.
You can't do this with int&. In that case, the presence or absence of const is really relevant for the caller, since the int referred to could be modified.