在C ++中,我倾向于在某些情况下省略参数的名称。但在C语言中,当我省略参数名称时出错了。
以下是代码:
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;
}
为什么?我不能在C函数定义中省略参数的名称吗?
答案 0 :(得分:33)
不,在C中,您不能省略函数定义中参数的标识符。
C99标准说:
[6.9.1.5]如果声明者包含参数类型列表,则 每个参数的声明应包括一个标识符,除了 参数列表的特例由单个参数组成 类型为void,在这种情况下不应有标识符。没有 声明清单应遵循。
C ++ 14标准说:
[8.3.5.11] 可以选择提供标识符作为参数 名称;如果存在于函数定义中,则为参数命名 (有时称为“正式论证”)。 [注意:特别是参数 名称在函数定义中也是可选的和用于a的名称 不同声明中的参数和函数的定义 不必相同。]
答案 1 :(得分:16)
原因在于这就是各自的语言标准所说的,但是存在差异的理由。
如果没有为参数提供名称,则该函数不能引用该参数。
在C中,如果一个函数忽略了它的一个参数,通常只需要从声明和定义中删除它,而不是在任何调用中传递它。异常可能是回调函数,其中函数集合必须是相同类型,但并非所有函数都必须使用它们的参数。但这不是一个非常常见的情况。
在C ++中,如果函数是从某个父类中定义的函数派生的,那么它必须与父元素具有相同的签名,即使子函数没有使用其中一个参数值。
(请注意,这与默认参数无关;如果C ++中的参数具有默认值,则调用者不必显式传递它,但如果函数定义要引用,则函数定义仍需提供名称它。)
答案 2 :(得分:5)
在纯粹的实践层面上,我每天都处理这个问题。迄今为止最好的解决方案是使用预处理器。我的公共头文件包含:
//-------------------------------------------------------------------------
// 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
使用UNUSED的一个例子是:
void foo(int UNUSED(bar)) {}
有时您实际需要引用参数,例如在assert()或debug语句中。您可以通过以下方式执行此操作:
#define USED_UNUSED(x) x##_UNUSED // for assert(), debug, etc
此外,以下内容非常有用:
#define UNUSED_FUNCTION(x) inline static x##_UNUSED // "inline" for GCC warning
#define SUPPRESS_UNUSED_WARNING(x) (void)(x) // cf. MSVC UNREFERENCED_PARAMETER
示例:
UNUSED_FUNCTION(int myFunction)(int myArg) { ...etc... }
和
void foo(int bar) {
#ifdef XXX
// ... (some code using bar)
#else
SUPPRESS_UNUSED_WARNING(bar);
#endif
}
答案 3 :(得分:4)
您可以省略函数原型中的参数名称,但必须在函数实现中声明它。例如,这在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;
}
输出:In foo with value 10 and 15!
至于为什么(除了因为标准这样说):C ++允许你在不使用所有参数的情况下调用函数,而C则不然。如果没有为C中的函数提供所有参数,则编译器将抛出error: too few arguments to function 'foo'