https://www.cnblogs.com/zhangpengshou/p/3587751.htmlhtml
http://m.elecfans.com/article/663750.htmllinux
https://www.cnblogs.com/LiuYanYGZ/p/5548855.html函數
https://blog.csdn.net/qq_33160790/article/details/78887349性能
c語言編譯分爲4個過程:優化
1:預編譯:預編譯作的事情爲:把僞指令轉換爲實際指令 命令 gcc -Eui
a:#define a b spa
b:#條件編譯指令,如#ifdef,#ifndef,#else,#elif,#endif等操作系統
c:#include 頭文件加入到編譯的文件中.net
d:一些符號處理如file local 等等;翻譯
# 1 "/usr/lib/gcc/x86_64-redhat-linux/4.4.7/include/stddef.h" 1 3 4 # 211 "/usr/lib/gcc/x86_64-redhat-linux/4.4.7/include/stddef.h" 3 4 typedef long unsigned int size_t; # 35 "/usr/include/stdio.h" 2 3 4 # 1 "/usr/include/bits/types.h" 1 3 4 # 28 "/usr/include/bits/types.h" 3 4 # 1 "/usr/include/bits/wordsize.h" 1 3 4 # 29 "/usr/include/bits/types.h" 2 3 4 typedef unsigned char __u_char; typedef unsigned short int __u_short; typedef unsigned int __u_int; typedef unsigned long int __u_long; typedef signed char __int8_t; typedef unsigned char __uint8_t; typedef signed short int __int16_t; typedef unsigned short int __uint16_t; typedef signed int __int32_t; typedef unsigned int __uint32_t; typedef signed long int __int64_t; typedef unsigned long int __uint64_t;
能夠看出一個很小的程序通過編譯之後把全部的頭文件包含進來都是很大的
2:編譯 命令是 gcc -S
把預編譯好的文件逐條轉化爲彙編語言
優化階段,通過預編譯獲得的輸出文件中,只有常量;如數字、字符串、變量的定義,
以及c語言的關鍵字,如main,if,else,for,while,{,}, +,-,*,\等等。
編譯程序所要做得工做就是經過詞法分析和語法分析,在確認全部的指令都符合語法規則以後,
將其翻譯成等價的中間代碼表示或彙編代碼。以下都是彙編代碼;操做寄存器
.file "test7.c" .text .globl power .type power, @function power: .LFB0: .cfi_startproc pushq %rbp .cfi_def_cfa_offset 16 .cfi_offset 6, -16 movq %rsp, %rbp .cfi_def_cfa_register 6 movl %edi, -20(%rbp) movl %esi, -24(%rbp) movl $1, -8(%rbp) movl -20(%rbp), %eax movl %eax, -4(%rbp) jmp .L2 .L3: movl -4(%rbp), %eax movl -20(%rbp), %edx imull %edx, %eax movl %eax, -20(%rbp) addl $1, -8(%rbp)
3:彙編 命令gcc -c
將.c文件直接編譯成.o的二進制文件:
4:連接 命令是 gcc *.c 連接命令是ld 連接的時候要考慮代碼和數據所要放的內存位置,能夠經過連接腳原本設置(這裏下次課再說)
連接程序的主要工做就是將有關的目標文件彼此相鏈接,也即將在一個文件中引用的符號同該符號在另一個文件中的定義鏈接起來,使得全部的這些目標文件成爲一個可以誒操做系統裝入執行的統一總體。
根據開發人員指定的同庫函數的連接方式的不一樣,連接處理可分爲兩種:
(1)靜態連接
在這種連接方式下,函數的代碼將從其所在地靜態連接庫中被拷貝到最終的可執行程序中。這樣該程序在被執行時這些代碼將被裝入到該進程的虛擬地址空間中。靜態連接庫其實是一個目標文件的集合,其中的每一個文件含有庫中的一個或者一組相關函數的代碼。
(2) 動態連接
在此種方式下,函數的代碼被放到稱做是動態連接庫或共享對象的某個目標文件中。連接程序此時所做的只是在最終的可執行程序中記錄下共享對象的名字以及其它少許的登記信息。在此可執行文件被執行時,動態連接庫的所有內容將被映射到運行時相應進程的虛地址空間。動態連接程序將根據可執行程序中記錄的信息找到相應的函數代碼。
對於可執行文件中的函數調用,可分別採用動態連接或靜態連接的方法。使用動態連接可以使最終的可執行文件比較短小,而且當共享對象被多個進程使用時能節約一些內存,由於在內存中只須要保存一份此共享對象的代碼。但並非使用動態連接就必定比使用靜態連接要優越。在某些狀況下動態連接可能帶來一些性能上損害。
=====================
gcc -o 指定文件名 如 gcc -c hello.c -o hello.a
gcc -M 只輸出編譯信息不編譯
gcc -MM 只輸出編譯信息不編譯