深入理解預編譯,編譯,彙編,鏈結的過程 之鏈結

2021-07-08 18:28:30 字數 1783 閱讀 8560

我們接觸程式的時候,一般編譯和鏈結是一起做的,所以不容易看到編譯和鏈結的不同,這裡我們講一下編譯和鏈結的區別。

範例1:

#main.c

int main()

對main.c生成執行檔案

$gcc -o main main.c

生成可執行檔案main(沒有字尾名),這個檔案什麼也不幹,但是可以執行。

gcc -o的過程同時呼叫了編譯和鏈結指令。

假如我們要在main中呼叫linuxframe.c中的startkernel()函式

範例2:

#main.c

#include "linuxframe.h"

int main()

這個時候我們編譯鏈結它

$gcc -o main main.c

undefined symbols for architecture x86_64:

"_startkernel", referenced from:

_main in main-856f96.o

ld: symbol(s) not found for architecture x86_64

clang: error: linker command failed with exit code 1 (use -v to see invocation)

說_startkernel這個函式在鏈結的時候系統找不到。

但是我們執行以下編譯指令

$gcc -c main.c

這個時候順利的生成main.o檔案

也就是說,main.c檔案編譯是可以的,沒有語法錯誤,但是鏈結的時候,就是去尋找startkernel()函式的時候,找不到了。要怎麼做呢?

試一下:

$gcc -o main main.c linuxframe.c

就沒有問題了,執行成功,順利的生成可執行檔案main(沒有字尾)

把linuxframe.c裡面新增乙個列印語句如下:

#include "stdio.h"

#include "linuxframe.h"

void loadbootcodefromexdisk();

void startkernel()

void loadbootcodefromexdisk()

$gcc -o main main.c linuxframe.c

順利生成可執行檔案main。執行main如下

$./main

順利輸出abcdefg。

這裡順便講一下.h檔案的作用,如果把main.c中的#include "linuxframe.h"語句去掉會怎麼樣?

#gcc -o main main.c linuxframe.c

main.c:14:5:warning:implicit declaration of function 'startkernel' is invalid in c99 [-wimplicit-function-declaration]

startkernel();

^

1 warning generated.

系統提示startkernel沒有定義。

缺少linuxframe.h,main.c和linuxframe.c就缺少了聯絡,main.c中呼叫的startkernel就不知道是linuxframe.c中的那個startkernel了。

執行以下生成的可執行檔案main

$./main

$什麼也沒有輸出。

預編譯,編譯,彙編,鏈結

2.編譯的工作內容 3.彙編的工作內容 4.鏈結器的工作內容 參考 include int main 使用gcc編譯器 gcc hello.c a.out a.out 含義是 assembler output 即 彙編輸出 上述過程可以分解為四個步驟 1.預處理 prepressing gcc e ...

C 預編譯 編譯 彙編 鏈結

windows中以2 2劃分核心 使用者空間,linux中以1 3劃分核心 使用者空間。在text段中,只有普通區域性變數是指令 int gdata1 10 data 已初始化且初始化不為零的資料 int gdata2 0 bss 未初始化或初始化為零的資料 int gdata3 bss stati...

深入理解include預編譯原理

1.include 命令的作用 1.1 什麼情況不使用 include 檔案 void test a 檔案 void test a 函式宣告 void test b 其實,這樣的工程,可以不用使用 include 預編譯命令。1.2 什麼情況使用 include 如果工程裡面的函式特別多,那麼按照上...