提前說明一下,我這個問題跟網上很多網友分享的問題不太一樣,而且我認爲導致問題出現的原因不重要,重點在於我分析這個問題的過程用到了一些知識,我認爲值得分享一下。
博客中用的到工程: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
六、找到問題所在,我們在步驟一的代碼中的函數聲明添加上這個關鍵字,編譯成功並運行: