数组与指针函数参数,有趣的 MSVC 行为

gez*_*eza 5 c++ visual-c++ language-lawyer

我注意到 MSVC 的一个有趣行为:具有数组参数的函数与具有指针参数的函数的损坏方式不同。

void foo(double a[3]);
Run Code Online (Sandbox Code Playgroud)

被破坏为?foo@@YAXQEAN@Z. 如果我将参数类型分解回来,它就是double * const(这就是编译器抱怨的,godbolt)。另一方面,

void foo(double *a);
Run Code Online (Sandbox Code Playgroud)

被破坏为?foo@@YAXPEAN@Z,破坏后的参数类型为double *。请注意损坏名称中的Q/差异。P这不仅仅是表面上的差异,如果函数定义和声明在这方面不匹配,我们会收到链接器错误。

这种行为是否符合标准?甚至,顶级const修饰符对链接器有意义吗?这是什么意思?

Lar*_*rry 0

评论太长了,但我同意@Remy(请参阅他的评论),我认为错误消息中的“const”没有明显的原因,因此怀疑它是一个错误,可能(仅限疯狂猜测),因为它最初可能会被标记“ a”作为“const”,因为数组不可分配(即使在这种情况下它不是真正的数组)。即使它在实际链接器错误中正确地将其视为指针类型,也可能忘记删除“const”。

无论实际情况是这样还是只是疯狂(牵强)的猜测(可能/可能),如果函数原型中的参数是值参数,那么它们通常不应该被声明为“const”(尽管我知道这里没有这样声明)但请继续阅读)。这会让读者感到困惑,因为它对调用者没有任何影响,并且对编译器本身没有技术上的差异(据我所知)。无论函数的签名是否为“const”,它都保持不变(同样,仅适用于值参数)。只有在函数的定义中,如果这些值没有在函数内部修改,您才会希望将它们设置为“const”,这与您在函数中本地定义的任何其他“const”变量没有什么不同(仅仅因为它们是参数,所以不会这方面的差异)。有关更多详细信息,请参阅“解决方案”部分中的第 1 条:https: //herbsutter.com/2013/05/28/gotw-6b-solution-const- Correctness-part- 2/ 。

结果是,就编译器而言(对于值参数),“const”对原型本身没有任何影响。它认为“double *”和“double * const”是相同的(在原型中),因此如果这就是它内部处理错误的方式(无论出于何种原因),它可以自由地显示您所看到的错误。然而,我仍然认为这是一个错误(或者非常令人困惑),以这种方式向最终用户显示它(假设“const”不存在于他们自己的代码中)。

注意(FWIW)“foo”的“decltype”仍然正确地将参数显示为“double *”(不存在“const”)