47

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?

Alcott
  • 17,905
  • 32
  • 116
  • 173
  • 2
    Writing multi-language source files is (very) hard work. I suggest you keep each single source file in one language only. – pmg Jan 08 '12 at 11:01
  • But if you do want something to compile in both C and C++, there's no need to write separate functions to use `printf` and `str::cout`. `printf` works for both languages. I'd recomment against using two functions that can be written as one, because of the possibility that their functionality might not be identical. – Mr Lister Jan 08 '12 at 11:28
  • 1
    In case the reason is -Wunused-parameter, there is a better solution: http://stackoverflow.com/a/3599170/1904815. – JonnyJD Feb 17 '14 at 12:54
  • In this case a space in memory to int is created and we just can't access it or the binary simple ignore the parameter? And if we call the function with some int as parameter a space in memory is reserved? – TheArchitect Dec 01 '17 at 14:46
  • It will be possible with [C2x/C23](https://en.wikipedia.org/wiki/C2x), but it is a new feature yet to come. – Schilive Oct 05 '22 at 02:00

4 Answers4

41

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.]

Destructor
  • 14,123
  • 11
  • 61
  • 126
adl
  • 15,627
  • 6
  • 51
  • 65
21

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.

Keith Thompson
  • 254,901
  • 44
  • 429
  • 631
7

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
}
Joseph Quinsey
  • 9,553
  • 10
  • 54
  • 77
3

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'

Rabbit
  • 566
  • 5
  • 13
  • 6
    C++ *doesn't* allow you to omit arguments in a call unless the corresponding parameters have default values. And in that case, the default values are passed implicitly, and the function has to provide names for the arguments if it's going to refer to their values. The difference is that there are more cases in C++ where it makes sense for a function to ignore one of its parameters. – Keith Thompson Jan 08 '12 at 11:24