extern“C”默认参数是否有效?

时间:2018-05-28 12:06:50

标签: c++ c arguments extern

Here开始,C似乎不支持默认参数。

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

extern "C" 
{
    __declspec (dllexport) uintptr_t Method(int freq, int *pRetval, bool *support2MHz);
}

如果我将最后一个参数设为可选,请执行以下操作:

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

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

我使用C ++ for MS 2015。

1 个答案:

答案 0 :(得分:7)

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

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

  

如果在参数声明中指定了 initializer-clause    initializer-clause 用作默认参数。默认参数   将在缺少尾随参数的调用中使用。

     

[例如:声明

void point(int = 3, int = 4);
     

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

point(1,2); point(1); point();
     

最后两次调用相当于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
     

- 结束示例]

因此,对于具有默认参数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"的具体示例中,这意味着编译器仅为Method生成一个带有C链接的符号,因此没有名称冲突。

您可以在live example on godbolt中看到各种编译器的此行为。

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