GCC的學習(一)GCC簡介及其常用選項

一、什麼是GCC

GCC(the GNU Compiler Collection)GCC是GNU編譯器集合
它包括了C/C++、Objective-C、Fortran、Ada和Go語言的前端和對應的庫(libstdc++)GCC初衷是爲完全免費的GNU系統編寫的編譯器。

二、程序到計算機執行

一個C程序從編輯到執行需要經過以下過程:

編寫並保存程序(.c)->預處理(.c)成文件(.i)->彙編(.i)文件成(.s)->編譯(.s)成(.o)->鏈接(.o/.so )成可執行->加載可執行文件並進行庫的動態鏈接->內存中的程序->CPU執行

二、GCC編譯過程

GCC就是完成從程序到可執行文件的編譯套件。其過程分爲四個部分:預處理、編譯、彙編和鏈接。

假如我編輯並保存瞭如下程序

//gcctest.cpp
#include <iostream>
using namespace std;
#define AAA 33333

int main()
{
    double a=3.14;//ordinary variable
    double &r=a;//ordinary referenece
    cout<<r<<endl;//read ok
    r=41.3;//write ok
    cout<<r<<endl;
    cout<<AAA<<endl;

    double b=3.14;
    const double &rr =b;//read only, restrict its own right
    cout<<rr<<endl;//read ok
    //rr=41.3;//write not ok
    //cout<<rr<<endl;

    const double c=3.14;
    // double &rrr=c;//reference trying to obtain read and write right failed
    // cout<<rrr<<endl;
    // rrr=41.3;
    // cout<<rrr<<endl;

    const double d=3.14;
    const double &rrrr=d;
    cout<<rrrr<<endl;
    //rrrr=41.3;
    //cout<<rrrr<<endl;
}

2.1 預處理 -E(Pre-pocessing)xxx.c->xxx.i

預處理會做三件事情,爲編譯做準備:

  • 宏變量替換
  • 頭文件展開
  • 註釋去除
    命令格式:gcc -E xxx.c
g++ gcctest.cpp -o app.i

這個-o其實指定生成文件名字標識(不指定默認生成a.out

這一階段生成的文件(xxx.i),還是可以很容易閱讀:

//...頭文件展開部分

using namespace std;

int main()
{
    double a=3.14;
    double &r=a;
    cout<<r<<endl;
    r=41.3;
    cout<<r<<endl;
    cout<<33333<<endl;

    double b=3.14;
    const double &rr =b;
    cout<<rr<<endl;



    const double c=3.14;





    const double d=3.14;
    const double &rrrr=d;
    cout<<rrrr<<endl;




}

2.2 編譯 -S(Compiling) xxx.i->xxx.s

編譯過後的文件稱爲彙編文件。命令格式:g++ xxx.i,這裏對上一部分的.i文件進行了處理:

g++ app.i -S -o app.s

仍然是個普通的文本文件,不過語言是彙編:

	.file	"class0919.cpp"
	.text
	.section	.rodata
	.type	_ZStL19piecewise_construct, @object
	.size	_ZStL19piecewise_construct, 1
_ZStL19piecewise_construct:
	.zero	1
	.local	_ZStL8__ioinit
	.comm	_ZStL8__ioinit,1,1
	.text
	.globl	main
	.type	main, @function
main:
.LFB1493:
	.cfi_startproc
	pushq	%rbp
	.cfi_def_cfa_offset 16
	.cfi_offset 6, -16
	movq	%rsp, %rbp
	.cfi_def_cfa_register 6
	subq	$80, %rsp
//... 省略了一大段彙編語言
.LC1:
	.long	1717986918
	.long	1078240870
	.hidden	__dso_handle
	.ident	"GCC: (Ubuntu 7.4.0-1ubuntu1~18.04.1) 7.4.0"
	.section	.note.GNU-stack,"",@progbits

2.3 彙編 -c(Assembling) xxx.s->xxx.o

彙編文件彙編後的文件類型是一個二進制文件,編譯過程中叫做目標文件,基本上人是沒法讀懂了:

亂碼

2.4 鏈接(Linking) xxx.o->xxx

對目標文件的集合稱爲可執行文件。命令g++ xxx1.o xxx2.o

g++ -o eee

內容一樣是亂碼,不過:

eee: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/l, for GNU/Linux 3.2.0, BuildID[sha1]=06ad229f773d4211a1a47719e43e93cc2886c5c3, not stripped

三、GCC其他選項

GCC不僅具有編譯成可執行的功能,還具有添加有用信息(-g)和打印信息(調試),甚至還可以調節優化等級(-On)。

option meaning
-o 指定生成的文件名
-E 僅執行編譯預處理
-S 將C代碼轉換爲彙編代碼
-wall 顯示警告信息
-c 僅執行編譯操作,不進行連接操作
-g 生成調試信息,不加選項不能進行gdb調試

查看GCC版本:

gcc --version
gcc -v

四、常見應用

3.1 無選項編譯

無選項編譯直接生成名爲a.out的可執行文件

gcc test.c

將test.c預處理、彙編、編譯並鏈接成可執行文件a.out

3.2 選項 -o

gcc test.c -o test

和無選項編譯一樣,只不過生成的可執行名字變成了test

3.3 選項 -E

僅預處理:

gcc -E test.c -o test.i

將test.c預處理輸出test.i文件。

3.4 選項 -c

僅編譯:

gcc -c test.s

將彙編輸出文件test.s編譯輸出test.o文件。

3.5 選項 -S

僅彙編:

gcc -S test.i

將預處理輸出文件test.i彙編成test.s文件。

3.6 選項-O

優化選項:

gcc -O1 test.c -o test

使用編譯優化級別1編譯程序。級別爲1~3,級別越大優化效果越好,但編譯時間越長

3.8 多個文件一起編譯

第一次生成可以使用:

gcc testfun.c test.c -o test

一起編譯+鏈接生成test可執行

僅對部分源文件進行了修改,使用-o選項更快:

gcc -c testfun.c    #將testfun.c編譯成testfun.o
gcc -c test.c       #將test.c編譯成test.o
gcc -o testfun.o test.o -o test    #將testfun.o和test.o鏈接成test
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章