考虑以下不执行任何操作的代码,我在 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/