【问题标题】:parameter name omitted, C++ vs C省略参数名称,C++ vs C
【发布时间】:2012-02-05 07:15:39
【问题描述】:

在 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函数定义中不能省略参数名吗?

【问题讨论】:

  • 编写多语言源文件是(非常)艰苦的工作。我建议您仅使用一种语言保存每个源文件。
  • 但是,如果您确实想要在 C 和 C++ 中编译某些东西,则无需编写单独的函数来使用 printfstr::coutprintf 适用于两种语言。我建议不要使用可以写成一个的两个函数,因为它们的功能可能不相同。
  • 如果原因是-Wunused-parameter,有更好的解决方案:stackoverflow.com/a/3599170/1904815
  • 在这种情况下,在内存中创建了一个 int 空间,我们无法访问它或者二进制简单地忽略参数?如果我们用一些 int 作为参数调用函数,内存中的空间会被保留吗?

标签: c++ c compilation


【解决方案1】:

不,在 C 中,您不能在函数定义中省略参数标识符。

C99 标准说:

[6.9.1.5] 如果声明符包含参数类型列表,则 每个参数的声明应包括一个标识符,除了 由单个参数组成的参数列表的特殊情况 void 类型,在这种情况下不应有标识符。不 申报清单如下。

C++14 标准说:

[8.3.5.11] 可以选择提供标识符作为参数 姓名;如果出现在函数定义中,它会命名一个参数 (有时称为“形式论证”)。 [注:特别是参数 名称在函数定义中也是可选的,并且名称用于 不同声明中的参数和函数的定义 不必相同。]

【讨论】:

  • 那么,变量名叫做标识符吗?
  • @Mr.TAMER:所有变量名都是标识符,但有些标识符不是变量名。
  • @DietrichEpp:我明白了,谢谢:)。通过快速搜索,我找到了this
  • @DietrichEpp,有些标识符不是变量名,比如?
  • @Alcott:类型名、函数名、宏名、标签名、标签名:都可以是标识符。
【解决方案2】:

原因是各自的语言标准是这样说的,但存在差异是有原因的。

如果您不提供参数名称,则函数无法引用该参数。

在 C 中,如果一个函数忽略了它的一个参数,通常只需将其从声明和定义中删除,而不是在任何调用中传递它。一个例外可能是回调函数,其中一组函数都必须属于同一类型,但并非所有函数都必须使用它们的参数。但这不是很常见的情况。

在 C++ 中,如果函数派生自某个父类中定义的函数,则它必须具有与父类相同的签名,即使子函数没有使用其中一个参数值。

(注意,这与默认参数无关;如果 C++ 中的参数有默认值,则调用者不必显式传递它,但函数定义仍然必须提供名称,如果它要引用给它。)

更新:C 标准的下一版本可能会允许省略参数名称。

【讨论】:

    【解决方案3】:

    在纯粹的实践层面上,我每天都在处理这个问题。迄今为止最好的解决方案是使用预处理器。我的常用头文件包含:

    //-------------------------------------------------------------------------
    //  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() 或调试语句中。您可以通过以下方式进行:

    #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
    }
    

    【讨论】:

    • 这晚了两天。我希望它不是unuseful。
    【解决方案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'

    【讨论】:

    • C++ 不允许 允许您在调用中省略参数,除非相应的参数具有默认值。在这种情况下,默认值是隐式传递的,如果函数要引用它们的值,则必须为参数提供名称。不同之处在于,在 C++ 中,函数忽略其参数之一是有意义的。
    猜你喜欢
    • 2017-10-28
    • 2013-10-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-24
    • 1970-01-01
    • 2011-06-27
    • 1970-01-01
    相关资源
    最近更新 更多