提前说明一下,我这个问题跟网上很多网友分享的问题不太一样,而且我认为导致问题出现的原因不重要,重点在于我分析这个问题的过程用到了一些知识,我认为值得分享一下。
博客中用的到工程:https://download.csdn.net/download/xundao255/11264177
(如果有经验的话,完全可以根据博客内容自己创建工程,毕竟下载工程是需要C币的。补充:我没找到怎么免C币下载资源,这个C币是系统自动设置的)
一、先列出源码和错误截图
#include <stdio.h>
int PrintString(unsigned int);
int main()
{
PrintString(3);
return 0;
}
PrintString(unsigned int)函数是“lib.lib”静态库中实现的函数,所以需要在工程的属性中隐性导入这个静态库。注意:这个静态库是存放在当前工程的路径下的。下面是编译失败的结果图:
注意上面截图的粗框线标注的函数“_PrintString”,这是编译器编译代码后,会按照固定规则修改函数名。上面的错误信息表示找不到函数的实现,也就是定义。
二、再来看一下实验用的lib静态库代码
#include <stdio.h>
int __stdcall PrintString(unsigned int a)
{
if (a < 5)
{
printf("小于5!\n");
}
else if (a == 5)
{
printf("等于5!\n");
}
else
{
printf("大于5!\n");
}
return 0;
}
这里放出代码,是为了说明函数什么功能,以及读者能自己做这个实验。在本博客中,我是假设不知道源代码的,只知道函数接口的声明而已和如何使用函数而已。
三、将步骤二中生成的“lib.lib”静态库放到步骤一的工程里面,使编译时能被找到。
四、当我发现出现了步骤一的错误后,逐渐排除了lib静态库没有成功加载的情况,也确定不是函数名写错了。此时,我就想看一下lib静态库的函数接口是什么样的,很有可能问题就出在这里。于是我再网上找到了方法,查看到lib静态库的接口信息:
Microsoft (R) COFF/PE Dumper Version 8.00.50727.42
Copyright (C) Microsoft Corporation. All rights reserved.
Dump of file C:\Users\Administrator\Desktop\input_lib\input_lib\lib.lib
File Type: LIBRARY
Archive member name at 8: /
5D16D10D time/date Sat Jun 29 10:46:37 2019
uid
gid
0 mode
9B size
correct header end
4 public symbols
1B8 ??_C@_07COGGELOH@?P?$KB?S?Z5?$CB?6?$AA@
1B8 ??_C@_07KIEDOMAO@?$LF?H?S?Z5?$CB?6?$AA@
1B8 ??_C@_07MOINBNDI@?$LE?s?S?Z5?$CB?6?$AA@
1B8 _PrintString@4
Archive member name at E0: /
5D16D10D time/date Sat Jun 29 10:46:37 2019
uid
gid
0 mode
9B size
correct header end
1 offsets
1 1B8
4 public symbols
1 ??_C@_07COGGELOH@?P?$KB?S?Z5?$CB?6?$AA@
1 ??_C@_07KIEDOMAO@?$LF?H?S?Z5?$CB?6?$AA@
1 ??_C@_07MOINBNDI@?$LE?s?S?Z5?$CB?6?$AA@
1 _PrintString@4
Summary
92C .debug$S
64 .debug$T
D7 .drectve
18 .rdata
4 .rtc$IMZ
4 .rtc$TMZ
8B .text
仔细看里面的函数接口显示为“_PrintString@4”,而不是“_PrintString”,这就解释清楚为什么找不到这个函数了。
关于如何查看静态库的接口,见我的另一篇博客:https://blog.csdn.net/xundao255/article/details/94128402
五、关于为什么“PrintString”编译成“_PrintString@4”,而不是“_PrintString”。
我们查看一下步骤二的代码:int __stdcall PrintString(unsigned int a),函数声明中加了“__stdcall”。这个关键字是给编译器看的,告诉编译器如何处理函数名称,后边的“@4”表示传参的数据类型的字节长度。详细说明见另一个大神写的博客:https://www.cnblogs.com/songfeixiang/p/3733661.html
六、找到问题所在,我们在步骤一的代码中的函数声明添加上这个关键字,编译成功并运行: