基礎學習——gcc編譯
編譯——就是一個將原始碼翻譯成計算機處理器能識別的語言的過程。
gcc
gcc是linux系統中通用的c編譯器。
舉例說明:
test.c
#include <stdio.h>
int main(void){
printf("Hello world\n");
return 0;
}
編譯命令如下:
gcc test.c -o test
生成可執行檔案test。實質上,上述編譯過程是分為四個階段進行的,即預處理(也稱預編譯,Preprocessing)、編譯(Compilation)、彙編 (Assembly)和連線(Linking)。
1. 預編譯(預處理Preprocessing)
預處理功能主要包括 巨集定義、檔案包含、條件編譯 三個部分。
預處理過程讀入原始碼,檢查包含預處理指令的語句和巨集定義,並對原始碼進行相應的轉換。預處理過程還會刪除程式中的註釋和多餘的空白字元。
預處理指令 是指 以#開頭的程式碼行。#號必須是該行除了任何空白字元外的第一個字元。#後是指令關鍵字,在關鍵字和#號之間允許存在任意個數的空白字元。整行語句構成了一條預處理指令,該指令將在編譯器進行編譯之前對原始碼做某些轉換。
gcc -E test.c -o test.i //可以檢視test.i,裡面存放著test.c經過預處理後的程式碼
或者
gcc -E test.c //直接在命令列視窗中輸出預處理後的程式碼
指令 用途
# 空指令,無任何效果
#include 包含一個原始碼檔案
#define 定義巨集
#undef 取消已定義的巨集
#if 如果給定條件為真,則編譯下面程式碼
#ifdef 如果巨集已經定義,則編譯下面程式碼
#ifndef 如果巨集沒有定義,則編譯下面程式碼
#elif 如果前面的#if給定條件不為真,當前條件為真,則編譯下面程式碼
#endif 結束一個#if……#else條件編譯塊
#error 停止編譯並顯示錯誤資訊
#else 略
#error 指令將使編譯器顯示一條錯誤資訊,然後停止編譯。
#line 指令可以改變編譯器用來指出警告和錯誤資訊的檔案號和行號。
#pragma 指令沒有正式的定義。編譯器可以自定義其用途。典型的用法是禁止或允許某 些煩人的警告資訊。
應用程式碼:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define SIX 6
#define SEVEN 7
#define Cube(x) (x)*(x)*(x)
#define VERSION "tzs"
#define PASTE(n) "最終勝利者是:"#n
#define NUM(a,b,c) a##b##c // 其中 ##代表連線符,將a,b,c連線在一起
#define STR(a,b,c) a##b##c
#define DEBUG 1
int main()
{
int i;
i = SIX + SEVEN;
printf("i = %d\n",i);
i = (SIX * SEVEN);
printf("i = %d\n",i);
i = Cube(3);
printf("i = %d\n",i);
printf("%s",VERSION);
printf("%s",PASTE(桃子));
puts(PASTE(yy/));
puts(PASTE(xx));
printf("%d\n",NUM(1,2,3));
//printf("%s\n",STR("aa","bb","cc"));
#if DEBUG
printf("Debugging\n");
printf("Debugging2222\n");
#endif
printf("Running\n");
#if defined DEBUG
printf("yes\n");
#endif
#if !defined JJ
printf("no JJ\n");
#endif
}
參考:
http://blog.csdn.net/dotphoenix/article/details/4345174
http://www.cnblogs.com/ligongzi/archive/2012/08/24/2654732.html
2. 編譯(Compilation,編譯為彙編程式碼)
預處理之後,可以直接對生成的 test.i 進行編譯,生成彙編程式碼:
gcc -S test.i -o test.s
gcc的-S選項,表示在程式編譯期間,在生成彙編程式碼後,停止,-o輸出彙編程式碼檔案。
3. 彙編
對上面生成的彙編程式碼test.s,gas彙編器負責將其編譯為目標檔案。
gcc -c test.s -o test.o
gas彙編器是Linux平臺的標準彙編器,它是gcc所依賴的後臺彙編工具,通常包含在binutils軟體包中。gas使用標準的AT&T彙編語法。
4. 連結
gcc聯結器是gas提供的,負責將程式的目標檔案與所需的所有附加的目標檔案連線起來,最終生成可執行檔案。附加的目標檔案包括靜態連線庫和動態連線庫。(連結器程式可以實現 編譯器的輸出 與 編譯程式所需要庫 之間的連結)
對於上面生成的test.o,將其與C標準輸入輸出庫進行連線,最終生成程式test。
gcc test.o -o test
執行./test即可輸出“Hello World!”。
庫是預編譯的目標檔案(object files)的集合,它們可被連結程式序。靜態庫以字尾為‘.a’的特殊的存檔檔案(archive file)儲存。
標準系統庫可在目錄 /usr/lib 與 /lib 中找到。比如,在類 Unix 系統中 C 語言的數學庫一般儲存為檔案 /usr/lib/libm.a。該庫中函式的原型宣告在標頭檔案 /usr/include/math.h 中。
C 標準庫本身儲存為 /usr/lib/libc.a,它包含 ANSI/ISO C 標準指定的函式,比如‘printf’。對每一個 C 程式來說,libc.a 都預設被連結。
參考:http://www.cnblogs.com/fly1988happy/archive/2012/03/31/2427274.html