c++ - 奇怪的 VS 名称修改行为?

标签 c++ visual-studio-2012 name-mangling

考虑以下不执行任何操作的代码,我在 Win10 64 位上将其编译为 C++:

int test(int argc, char *argv[]);
int main(int argc, char *argv[])
{
   return test(argc, argv);
}

int test(int argc, char **argv)
{
   return 0;
}

如果所有这些代码都放在同一个 .cpp 文件中,它会在 VS2012、VS2013、VS2015 和 mingw32-g++ v4.7.1 中正确编译和链接,正如我所期望的那样。

但是,如果我只是将测试函数的定义移动到一个单独的文件中,生成的两个文件仍然可以编译并使用 mingw 编译器正确链接,但在所有版本的 VS 上我得到:

error LNK2019: unresolved external symbol "int __cdecl test(int,char * * const)" (?test@@YAHHQAPAD@Z) referenced in function _main"

我可以通过简单地将测试函数中参数 argv 的声明更改为 char *argv[] 来解决 VS 中的这个问题,但这不是必需的,因为 char *argv []char **argv 用于声明参数时的含义完全相同。

我还没有尝试过,但这让我想知道 VS 是否也会出于重载目的考​​虑这两个不同的版本。

最佳答案

是的,这是 Visual C++ 名称修饰方案中的错误。对于指针类型参数,顶级 const 和 volatile 限定符被编码到修饰名称中,即使它们与函数的类型无关。因此,例如,char**char** const 的编码方式不同。 (在您的示例中,char*[] 等同于 char** const。)

在确定如何修饰函数名时,编译器将使用函数的第一个声明,即使定义与第一个声明不完全匹配。这就是当定义与 main 函数位于同一源文件中时您的示例链接的原因:测试函数使用第一个声明所需的名称修饰,该名称与 main 函数中引用的名称相同。

如果您将声明和定义都移动到单独的源文件中,例如,

int test(int argc, char *argv[]);

int test(int argc, char **argv)
{
   return 0;
}

那么你的程序也会链接成功,同理。这就是为什么这个“错误”通常不是问题:通常当函数在多个翻译单元中使用时,它们在头文件中声明,并且到处都包含一个声明。

关于c++ - 奇怪的 VS 名称修改行为?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32447978/

相关文章:

c++ - OpenGL 不绘制三角形

python - 正确使用ctypes来调用_Py_Mangle?

html - CSS中的 `lightgrey`和 `lightgray`有什么区别?

InfoPath 表单中的 C# 字符串插值

c++ - 无法从 .dat 文件读取数据(从 Simulink 创建的 VS2012 C++ 项目)

c++ - 从 C++ 链接到 Fortran 库 (Lapack)

c++ - Mingw 的处理/导出问题

c++ - boost 无法使用 gcc move scoped_lock

c++ - MSVS2012 c++ nmake 如何在子目录中的 makefile 上运行 nmake?

c++ - 将 double 组转换为仅具有 double 成员的结构数组而不复制数据