#include <stdio.h>
int myentry() {
printf("hello world");
return 0;
}
編譯 cl /c hello.c 成功產生 hello.obj;連結 link hello.obj 報錯:
LIBC.lib(crt0.obj) : error LNK2001: unresolved external symbol _main hello.exe : fatal error LNK1120: 1 unresolved externals
cl 未加 /Zl,hello.obj 內含兩個 defaultlib 指示:libc.lib 與 oldnames.lib。libc.lib,其中包含 crt0.obj(來自 crt0.c),定義了 mainCRTStartup。mainCRTStartup 內部呼叫 main,但 hello.obj 只定義 myentry,缺少 _main 符號 → LNK2001。與編譯階段不同,連結器要求所有外部符號皆須解析,即使該函式在執行路徑上永不被呼叫。示例:
int myentry() { printf("hello world"); return 0; }
int main() { myentry(); }
int test() { nofunc(); return 0; } // test 未被呼叫,nofunc 未定義
連結仍報錯 unresolved external symbol _nofunc。這是 C/C++ 編譯模型(編譯→連結→執行三階段)特有的複雜性。
| 方式 | 編譯指令 | 連結指令 | 結果 |
|---|---|---|---|
| Way1:改回 main | cl /c /Zl hello.c | link hello.obj | 缺 _printf、_mainCRTStartup |
| Way2:指定 entry=myentry | cl /c /Zl hello.c | link /entry:myentry hello.obj | 錯 LNK1221:無法推斷 subsystem |
| Way2+subsystem | cl /c /Zl hello.c | link /entry:myentry /subsystem:console hello.obj | 缺 _printf |
| Way3:main + entry=main | cl /c /Zl hello.c | link /entry:main /subsystem:console hello.obj | 缺 _printf |
LNK2001:未解析的外部符號(函式/變數/標籤)LNK1561:找不到入口點(需 /ENTRY 或提供 main/WinMain 等)LNK1221:無法推斷 subsystem,需加 /SUBSYSTEM:CONSOLE 或 WINDOWS連結器根據 defaultlib、/ENTRY、/SUBSYSTEM、符號定義/引用關係,自動推導或強制指定程式屬性。理解這套規則,才能在「脫離 IDE」時精準控制輸出。