gcc/g++命令使用及編譯原理一

gcc/g++命令使用GNU推出的基於C/C++的編譯器,是開放源代碼領域應用最廣泛的編譯器,具有功能強大,編譯代碼支持性能優化等特點。現在很多程序員都應用GCC,怎樣才能更好的應用GCC。目前,GCC可以用來編譯C/C++、FORTRAN、JAVA、OBJC、ADA等語言的程序,可根據需要選擇安裝支持的語言。

0x1.什麼是編譯器?

    簡單講,編譯器就是將“一種語言(通常爲高級語言)”翻譯爲“另一種語言(通常爲低級語言)”的程序。舉個例子:當我們使用C語言寫了一段程序,想被運算機器執行(電腦或其它嵌入式設備等等),編譯器就是負責把這一段程序轉換成可以指定機器上執行的指令。

0x2.工作流程

    gcc編譯主要工作流程有四個部分:預處理(preprocessing),編譯(compilation),彙編(assembly),鏈接(linking),當前網絡上還有其它的表現形式,如:源代碼 (source code) → 預處理器 (preprocessor) → 編譯器 (compiler) → 目標代碼 (object code) → 鏈接器 (Linker) → 可執行程序 (executables),其實原理都一樣,只是後面的更方便理解。關於編譯原理有詳情說明。


0x3.gcc常用命令

語法:gcc (選項)(參數:文件)
    寫一個hello.c的程序

#include<stdio.h>

int main(){
	printf("hello world!");
	return 0;
}

1、無選項編譯鏈接 

$ gcc hello.c

hello.c預處理、編譯、彙編並鏈接形成可執行文件。這裏未指定輸出文件,在Linux上默認輸出爲a.out,在window環境中編譯默認爲a.exe。

 $ ls
 a.exe  hello.c

查看生成a.exe執行文件

$ ./a.exe
hello world!

執行a.exe,輸出結果
    
2、選項 -o(理解成output),對生成的目標進行重命名,linux下爲hello.out,windows下爲hello.exe

$ gcc -o hello hello.c

$ ls
a.exe  hello.c  hello.exe

3、選項 -E,把源代碼預處理輸出爲hello.i文件,詳見下一篇

$ gcc -E hello.c -o hello.i

$ ls
a.exe  hello.c  hello.exe  hello.i

與cpp  hello.c  >  hello.i命令功能一致。

4、選項 -S,把預處理輸出的文件hello.i彙編成hello.s文件

$ gcc -S hello.i
$ ls
a.exe  hello.c  hello.exe  hello.i  hello.s

查看彙編後hello.s的內容

	.file	"hello.c"
	.text
	.def	__main;	.scl	2;	.type	32;	.endef
	.section .rdata,"dr"
.LC0:
	.ascii "hello world!\0"
	.text
	.globl	main
	.def	main;	.scl	2;	.type	32;	.endef
	.seh_proc	main
main:
	pushq	%rbp
	.seh_pushreg	%rbp
	movq	%rsp, %rbp
	.seh_setframe	%rbp, 0
	subq	$32, %rsp
	.seh_stackalloc	32
	.seh_endprologue
	call	__main
	leaq	.LC0(%rip), %rcx
	call	printf
	movl	$0, %eax
	addq	$32, %rsp
	popq	%rbp
	ret
	.seh_endproc
	.ident	"GCC: (GNU) 7.3.0"
	.def	printf;	.scl	2;	.type	32;	.endef

5、選項 -c,把彙編成hello.s文件編譯輸出爲hello.o文件,輸出文件爲二進制目標文件。

$ gcc -c hello.s
$ ls
a.exe  hello.c  hello.exe  hello.i  hello.o  hello.s

與as hello.s -o hello.o命令功能一致。

在IDA工具中查看hello.o文件

6、無選項鍊接,把hello.o目標文件鏈接成最終可執行文件hello1.exe,其實是調用ld命令進行鏈接。

$ gcc hello.o -o hello1
$ ls -l
總用量 394
-rwxrwxr-x+ 1 Administrator  None 155707 八月  3 15:31 a.exe
-rwxrwx---+ 1 Administrators None     68 八月  3 15:21 hello.c
-rwxrwxr-x+ 1 Administrator  None  34373 八月  3 16:48 hello.exe
-rw-rw-r--+ 1 Administrator  None  34373 八月  3 16:48 hello.i
-rw-rw-r--+ 1 Administrator  None    866 八月  3 17:18 hello.o
-rw-rw-r--+ 1 Administrator  None    496 八月  3 17:05 hello.s
-rwxrwxr-x+ 1 Administrator  None 155707 八月  3 17:26 hello11.exe

$ ./hello1.exe
hello world!

7、選項 -O(大寫的字母O),使用編譯優化級別,1~3,級別越大優化效果越好,但編譯的時候會長。

$ gcc -O3 hello.c -o hello2

8、選項 -M,查看生成文件關聯信息,包含目標文件所依賴的所有源代碼,該命令會在預處理階段中執行。

$ gcc -M hello.c
hello.o: hello.c /usr/include/stdio.h /usr/include/_ansi.h \
 /usr/include/newlib.h /usr/include/_newlib_version.h \
 /usr/include/sys/config.h /usr/include/machine/ieeefp.h \
 /usr/include/sys/features.h /usr/include/cygwin/config.h \
 /usr/include/sys/cdefs.h /usr/include/machine/_default_types.h \
 /usr/lib/gcc/x86_64-pc-cygwin/7.3.0/include/stddef.h \
 /usr/lib/gcc/x86_64-pc-cygwin/7.3.0/include/stdarg.h \
 /usr/include/sys/reent.h /usr/include/_ansi.h /usr/include/sys/_types.h \
 /usr/include/machine/_types.h /usr/include/sys/lock.h \
 /usr/include/sys/types.h /usr/include/sys/_stdint.h \
 /usr/include/machine/endian.h /usr/include/machine/_endian.h \
 /usr/include/bits/endian.h /usr/include/sys/select.h \
 /usr/include/sys/_sigset.h /usr/include/sys/_timeval.h \
 /usr/include/sys/timespec.h /usr/include/sys/_timespec.h \
 /usr/include/sys/_pthreadtypes.h /usr/include/machine/types.h \
 /usr/include/endian.h /usr/include/bits/byteswap.h \
 /usr/include/bits/wordsize.h /usr/include/sys/sysmacros.h \
 /usr/include/sys/stdio.h

9、選項 -MM,與-M相比,會忽略#include文件的依賴關係

$ gcc -MM hello.c
hello.o: hello.c

10、多個文件一起編譯,hello.c、multi.c分別編譯後鏈接成multi.out或multi.exe的可執行文件。

$ gcc hello.c multi.c -o multi

11、多個.o二進制目標文件編譯後鏈接成一個可執行文件

$ gcc multi.o hello.o -o multi1

12、選項 -include file :包含某個代碼。相當於在文件中加入#include 

$ gcc hello.c -include multi.c -o include

生成include.out可執行文件

13、選項 -Idir:當你使用#include”file”的時候,會先到你定製的目錄裏面查找。

14、選項 -L(library):定製編譯的時候使用的庫,/home/hello/lib作爲第一個尋找庫文件的目錄。

$ gcc -o hello hello.c -L/home/hello/lib

15、選項 -l:定製編譯的時候使用的庫,尋找動態鏈接庫文件libtest.so,如果加上-static,表示尋找libtest.a靜態鏈接庫。

$ gcc -o hello hello.c -ltest

16、選項 -w,表示不生成任何警告的信息。

$ gcc -w multi.c hello.c -o multi

17、選項 -Wall:生成所有警告信息。

$ gcc -Wall multi.c hello.c -o multi

18、選項 -g:在編譯的時候加入debug調試信息,用於gdb調試,文件會比一般大一點。

$ gcc -g hello.c -o hello5

19、選項 -share:此選項儘量的使用動態庫,所以生成文件比較小,但是必須是系統有動態庫。

20、選項 -shared:生成共享目標文件,通常用在建立共享庫。

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