做網(wǎng)站推廣優(yōu)化淘寶排名查詢工具
1 前言
1.1 環(huán)境
? ? ? ? 平臺(tái):uabntu20.04
? ? ? ? 工具:vim,gcc,make
1.2 GCC
????????
Linux系統(tǒng)下的GCC(GNU Compiler Collection)是GNU推出的功能強(qiáng)大、性能優(yōu)越的多平臺(tái)編譯器,是GNU的代表作品之一。gcc是可以在多種硬體平臺(tái)上編譯出可執(zhí)行程序的超級(jí)編譯器,其執(zhí)行效率與一般的編譯器相比平均效率要高20%~30%。
GCC編譯器能將C、C++語言源程序、匯程式化序和目標(biāo)程序編譯、鏈接成可執(zhí)行文件,如果沒有給出可執(zhí)行文件的名字,gcc將生成一個(gè)名為a.out的文件。
GCC編譯器編譯C源文件為可執(zhí)行文件的步驟:
C源文件—->預(yù)處理.i—->編譯.s(生成匯編文件)—->匯編.o/.obj(生成目標(biāo)文件)—->鏈接.out(生成可執(zhí)行文件)—->可執(zhí)行文件
gcc命令參數(shù)(選項(xiàng))
參數(shù)?? ?含義?? ?示例
參數(shù) | 含義 | 示例 |
-c | 對(duì)文件進(jìn)行預(yù)處理、編譯和匯編,生成obj文件?? ? | gcc -c hello.c |
-S? | 只進(jìn)行預(yù)處理和編譯,生成匯編代碼 | gcc -S hello.c |
-E | 只進(jìn)行預(yù)處理,這個(gè)選項(xiàng)不生成文件,可以使用重定向或者-o選項(xiàng)使其生成一個(gè)文件 | ?gcc -E hello.c > hello.i或者gcc -E hello.c -o hello.i |
-o | ?指定目標(biāo)的名稱,默認(rèn)為a.out | gcc -o hello hello.c |
?? ?? ?
過程演示
例如源代碼main.c:
#include<stdio.h>int main(void) {printf("Hello World!\n");return 0;
}
預(yù)編譯:這個(gè)過程處理宏定義和include,去除注釋,不會(huì)對(duì)語法進(jìn)行檢查??梢钥吹筋A(yù)編譯后,源文件的代碼從6行擴(kuò)展了很多行,生成main.i
gcc -E main.c > main.i # 或者 gcc -E main.c -o main.i
// ...
// 只展示了一部分
extern int ftrylockfile (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__)) ;extern void funlockfile (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__));
# 943 "/usr/include/stdio.h" 3 4# 2 "main.c" 2
int main(void) {printf("Hello World!\n");return 0;
}
編譯:這個(gè)階段,檢查語法,生成匯編代碼main.s
gcc -S main.c -o main.s
.file "main.c".section .rodata
.LC0:.string "Hello World!".text.globl main.type main, @function
main:
.LFB0:.cfi_startprocpushq %rbp.cfi_def_cfa_offset 16.cfi_offset 6, -16movq %rsp, %rbp.cfi_def_cfa_register 6movl $.LC0, %edicall putsmovl $0, %eaxpopq %rbp.cfi_def_cfa 7, 8ret.cfi_endproc
.LFE0:.size main, .-main.ident "GCC: (GNU) 4.8.5 20150623 (Red Hat 4.8.5-44)".section .note.GNU-stack,"",@progbits
匯編:這個(gè)階段,生成目標(biāo)代碼main.o
gcc -c main.s -o main.o
鏈接:生成可執(zhí)行代碼main。
鏈接分為兩種,一種是靜態(tài)鏈接,另外一種是動(dòng)態(tài)鏈接。
使用靜態(tài)鏈接的好處是,依賴的動(dòng)態(tài)鏈接庫較少,對(duì)動(dòng)態(tài)鏈接庫的版本不會(huì)很敏感,具有較好的兼容性;缺點(diǎn)是生成的程序比較大。
使用動(dòng)態(tài)鏈接的好處是,生成的程序比較小,占用較少的內(nèi)存。
?
gcc main.o -o main
?運(yùn)行
[root@HongyiZeng c]# ./main
Hello World!
?
1.3 make
make命令是GNU工程化中的一個(gè)編譯工具。make是依賴于Makefile來編譯多個(gè)源文件的工具。在Makefile里同樣是用gcc(或者別的編譯器)來編譯程序。
可以使用以下命令直接生成可執(zhí)行文件:
make main
直接運(yùn)行
[root@HongyiZeng c]# ./main
Hello World!
?1.4 makefile
一個(gè)工程中的源文件不計(jì)其數(shù),其按類型、功能、模塊分別放在若干個(gè)目錄中,makefile定義了一系列的規(guī)則來指定哪些文件需要先編譯,哪些文件需要后編譯,哪些文件需要重新編譯,甚至于進(jìn)行更復(fù)雜的功能操作。
?1.4.1 使用gcc的例子
創(chuàng)建文件:
touch main.c tool1.c tool1.h tool2.c tool2.h
可以使用vim * -p打開當(dāng)前目錄下的所有文件。-p是打開多個(gè)文件的選項(xiàng)。
在命令模式下,gt切換到下一個(gè)標(biāo)簽頁,gT切換到上一個(gè)標(biāo)簽頁。
退出多個(gè)標(biāo)簽時(shí),可加上a,例如:qa或者:wqa等
tool1.h和tool1.c
#ifndef __TOOL1_H__
#define __TOOL1_H__void mytool1();
#endif
#include <stdio.h>
#include "tool1.h"
void mytool1() {printf("tool1 print...\n");
}
tool2.h和tool2.c
#ifndef __TOOL2_H__
#define __TOOL2_H__void mytool2();
#endif
#include <stdio.h>
#include "tool2.h"void mytool2() {printf("tool2 print...\n");
}
main.c
#include "tool1.h"
#include "tool2.h"int main(void) {mytool1();mytool2();return 0;
}
對(duì)所有文件進(jìn)行編譯:
gcc *.c
執(zhí)行a.out
[root@HongyiZeng makefile]# ./a.out
tool1 print...
tool2 print...