extern"C"默认参数是否有效?

Eri*_*tný 8 c c++ arguments extern

这里看来,C不支持默认参数.

我在导出的库中有以下方法:

extern "C" 
{
    __declspec (dllexport) uintptr_t Method(int freq, int *pRetval, bool *support2MHz);
}
Run Code Online (Sandbox Code Playgroud)

如果我使最后一个参数可选像这样:

extern "C" 
{
    __declspec (dllexport) uintptr_t Method(int freq, int *pRetval, bool *support2MHz = NULL);
}
Run Code Online (Sandbox Code Playgroud)

我的dll仍在编译中.我的问题是为什么?每个人都说C代码不支持默认参数.

我使用C++ for MS 2015.

Gor*_*gar 8

正如molbdnilo在评论中已经注意到的那样,extern "C"并不意味着"这是C代码",而是"这是带有C链接的代码" - 即不会执行此函数的名称修改,因此您可以从C调用它"预期"函数调用语法.C++编译器破坏了函数的名称,因此它们可以支持函数重载,因为同一函数的不同重载的符号名称必须是唯一的(基本上,它们使用函数的作用域,名称和参数类型来创建唯一的符号名称).

根据[dcl.fct.default],该标准第1和第2段:

如果在参数声明中指定了initializer子句,则此 initializer子句将用作默认参数.默认参数将用于缺少尾随参数的调用中.

[例子:声明

void point(int = 3, int = 4);
Run Code Online (Sandbox Code Playgroud)

声明一个可以使用零个,一个或两个类型参数调用的函数 int.它可以通过以下任何方式调用:

point(1,2); point(1); point();
Run Code Online (Sandbox Code Playgroud)

最后两个调用分别等同于point(1,4)point(3,4). - 结束例子]

此外,第9段规定:

默认参数不是函数类型的一部分.[例如:

int f(int = 0);

void h() {
    int j = f(1);
    int k = f();                      // OK, means f(0)
}

int (*p1)(int) = &f;
int (*p2)() = &f;                   // error: type mismatch
Run Code Online (Sandbox Code Playgroud)

- 结束例子]

因此,对于具有默认参数的函数int foo(int x, int y = 0),编译器不会生成两个重载(int foo(int x, int y)int foo(int x),具有y固定到0),而是替换的形式的每一个电话foo(x)与一个呼叫foo(x, 0).在你的具体例子中,extern "C"这意味着编译器只生成一个带有C链接的符号,Method因此没有名称冲突.

您可以在godbolt的实例中看到各种编译器的这种行为.

但是,正如Afshin在评论中已经提到的那样,实现它的方式使得无法将默认参数"传播"到共享库的其他用户,所以如果你想从C中使用它,你仍然需要通过所有函数的参数.