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

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

範例1:

#main.c

int main(){


    return 0;

}

對main.c生成執行文件
$gcc -o main main.c
生成可執行文件main(沒有後綴名),這個文件什麼也不幹,但是可以執行。
gcc -o的過程同時調用了編譯和鏈接指令。


假如我們要在main中調用LinuxFrame.c中的startkernel()函數
範例2:
#main.c

#include "LinuxFrame.h"

int main(){


    startkernel();


    return 0;

}

這個時候我們編譯鏈接它
$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(){


    LoadBootCodeFromExDisk();

    printf("abcdefg\n");


}



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
$
什麼也沒有輸出。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章