1. 程式人生 > >C源程式到可執行檔案的步驟

C源程式到可執行檔案的步驟

大家都知道,計算機只認識0 1 二進位制數,我們編寫程式也是為了讓計算機按照人的思維完成相應的操作,我們編寫的程式程式碼計算機並不認識,所以需要翻譯成計算機能夠認識的機器語言,不同的計算機機器程式碼不一樣,所以就需要編譯器來實現中間的步驟,那從我們的.c檔案到計算機可執行的檔案中間到底經過了哪些步驟呢?

c原始檔—->編譯預處理—->編譯程式—->優化程式—->彙編—->連結程式—->可執行檔案

1.編譯預處理階段
載入標頭檔案、巨集替換、條件編譯的作用。一般處理“偽指令”(帶“#”的語句)和一些特殊符號,主要分為以下幾類:
(1)巨集定義指令,如#define,#undef等,進行巨集替換和取消巨集定義。
(2)條件編譯指令,如#ifdef,#ifndef,#else,#elif,#endif,等,讓程式可以選擇性的編譯。
(3)標頭檔案包含指令,如#include “”或者#include <>等。預編譯程式將把標頭檔案中的定義加入到產生的輸出檔案中,以供編譯程式處理。
(4)特殊符號,預編譯程式可以識別一些特殊的標識。
我們可以通過指令來檢視,(hello.c)

[[email protected] c]# gcc -E hello.c

2.編譯階段
編譯程式工作就是通過詞法分析和語法分析,在確認所有的指令都符合語法規則之後,將其翻譯成等價的中間程式碼表示或彙編程式碼,生成(.o)檔案
我們可以通過指令來檢視,(hello.c)

[[email protected] c]# gcc -c hello.c

3.優化階段
優化一方面是對中間程式碼的優化,另一種則針對目的碼的生成而進行的。對程式碼的檢查,主要是刪除公共表示式、迴圈優化、複寫傳播,以及無用賦值的刪除,後一種優化同機器的硬體結構密切相關,考慮如何充分利用機器的各個硬體暫存器存放的有關變數的值,以減少對於記憶體的訪問次數,提高效率。
4.彙編階段


把彙編程式碼翻譯成目標機器指令的過程。目標檔案由段組成。通常一個目標檔案中至少有兩個段:
程式碼段 :該段中所包含的主要是程式的指令。一般是可讀和可執行不可寫。
資料段:存放程式用到的各種全域性變數或靜態的資料。一般是可讀可寫可執行。
我們可以通過指令來檢視生成(.s)彙編檔案

[[email protected] c]# gcc -S hello.c

5.連結
將有關的目標檔案彼此相連線,使得所有的這些目標檔案成為一個能夠被作業系統裝入執行的統一整體,這個檔案可被載入或拷貝到儲存器執行,在我的上一遍博文中也有講過連結就是將各種目標檔案根據他們之間呼叫關係聯絡到一起,才能成為整個工程的機器程式碼,開發人員指定同庫函式的連結方式的不同,連結處理可分為兩種:
(1)靜態連結—函式的程式碼將從靜態連結庫(實際是一個目標檔案的集合,其中每個檔案含有庫中相關函式的程式碼)拷貝

到最終的可執行程式中。這樣該程式在被執行時這些程式碼將被裝入到該程序的虛擬地址空間中
(2)動態連結—函式的程式碼被放到動態連結庫或共享物件的某個目標檔案中。連結程式所作的只是在最終的可執行程式中記錄下共享物件的名字以及其它少量的登記資訊。執行時,動態連結庫的全部內容將被對映到程序的虛地址空間。動態連結程式將根據可執行程式中記錄的資訊找到相應的函式程式碼,使最終可執行檔案較短小,並且當共享物件被多個程序使用時能節約一些記憶體,因為在記憶體中只需要儲存一份共享物件的程式碼。
我們可以通過指令來檢視,(hello.c)

[[email protected] c]# gcc hello.o -o hello
生成hello執行檔案,如下
[[email protected] c]# gcc hello.c -o hello
[[email protected] c]# ./hello
hello world
經過這5個步驟,就可以生成可執行檔案了,Windows下預設為a.exe,Linux下預設為a.out,在該目錄下執行就可以了

補充
目標檔案有三種形式:
1> 可重定位的目標檔案:含二進位制程式碼和資料,其形式可以在編譯時與其它可定位目標檔案合併起來,建立一個可執行目標檔案。
2> 可執行目標檔案:包含二進位制程式碼和資料,其形式可以被直接拷貝到儲存器並執行,也就是最後形成的檔案。
3> 共享目標檔案:一種特殊的可重定位目標檔案,可以在載入或執行時,被動態加到儲存器並執行。

編譯器和彙編器生成可重定位目標檔案(包括共享目標檔案),連結器生成可執行目標檔案。

相關推薦

Linux C執行檔案結構以及程序結構

(公共部分):程式碼區,BSS區,資料區. 1.程式碼區:存放可執行的指令.順便規劃局部變數的相關資訊(??).   獨有性:一份指令在記憶體(不管虛擬記憶體還是實際)中只要有一份就可以的   只讀性:彙編指令包含 操作碼+運算元;一般操作碼是不可變的,但是運算元可

在linux下把python檔案打包成執行檔案步驟

1.安裝PyInstaller    pip install pyinstaller    pyinstaller --version2.使用PyInstaller打包python檔案  在和myscript.py同目錄下執行命令:pyinstaller mycript.py

ubuntu生成C語言執行檔案

最重要的是寫CMakeLIst.txt檔案。 寫好CMakeLIst之後,使用cmake-gui。在terminal輸入cmake-gui,開啟介面如下: 選擇unix makefiles 點選finish之後,再分別點選configure和genera

C#呼叫執行檔案(.bat,.exe...)

在伺服器開發的過程中,我們經常需要開多個黑框測試功能,在資料夾中找這些可執行檔案十分的浪費時間 帶來的個人體驗也異常的差勁,我們可以通過C#製作一些小工具來改善這種情況,比如把需要開啟的多個黑框

C源程式執行檔案步驟

大家都知道,計算機只認識0 1 二進位制數,我們編寫程式也是為了讓計算機按照人的思維完成相應的操作,我們編寫的程式程式碼計算機並不認識,所以需要翻譯成計算機能夠認識的機器語言,不同的計算機機器程式碼不一樣,所以就需要編譯器來實現中間的步驟,那從我們的.c檔案到計

Linux C 源程式 編譯連線生成 執行檔案

源程式 test.c第一種 ,編譯 gcc -c test.c -o test.o              連線 gcc -o test test.o第二種。              編譯連線              gcc -o test test.c執行    ./

C++原始碼生成執行檔案的四個步驟

以GCC編譯器為例: 第一步,預處理,包括語法檢查等工作。 $ gcc -P abc.c 會生成abc.i檔案。 第二步,編譯,由源程式生成組合語言程式碼。 $ gcc -S abc.c 會生成abc.s檔案,這個檔案就是彙編程式碼。 第三步,彙編,編譯器生成目的碼,一個源

C程式碼變成執行檔案的過程

C程式碼是如何變成程式的 C語言是一門典型的編譯語言,原始碼檔案需要編譯成目的碼檔案才能執行。可以認為程式檔案就是編譯好的目的碼檔案。以GCC的編譯過程為例。GCC的翻譯過程可以分成四個階段:前處理器、編譯器、彙編器、連結器,執行這四個階段的程式一起構成了一個編譯系統。 前

軟體素材---linux C語言:linux下獲取執行檔案的絕對路徑--getcwd函式

      //標頭檔案:#include <unistd.h>     //定義函式:char * getcwd(char * buf, size_t size);    

C語言】概述從原始碼到執行檔案

自第一次輸出“hello world” 「原始碼如何變成可執行檔案」的問題就一直伴隨著我 本次以《程式設計師的自我修養—連結、裝載與庫》為參考,對這一過程做簡單總結 簡介 高階語言的出現使得程式設計師可以 儘量少考慮計算機本身的限制(如字長、記憶體大小、通訊方式

C# 基礎(十三)C# 軟體開發過程中,執行檔案.exe 出現bug,該怎麼排查、解決:找到出現bug的位置

一、簡介 之前是完成了寫軟體,從而實現軟體的基本功能。到了今天,需要對自己寫的可執行檔案.exe找bug了。那麼下面,我將結合自己的軟體的使用過程中,講自己的經驗融入進來,解釋下什麼是bug、以及該怎麼找Bug。 二、Bug的分類 主要參考: https://blog.csdn.ne

c#程式打包成執行檔案

經過朋友(lcm)的耐心指導,輕鬆完成了c#程式的打包,希望能夠幫助更多的戰友輕鬆打包c#。 一:前期準備工作 使用《innosetup_5.5.9》工具實現c#程式打包,程式下載地址:   htt

Android系統開機啟動C執行檔案

在工作中有一個需求是android手機開機啟動一個C可執行檔案,起初嘗試是將在android原始碼裡面寫一個bash指令碼,然後在腳本里面執行/data目錄下的可執行檔案,然後將系統燒寫進手機,開機後將可執行檔案放入手機/data目錄裡面,然後重啟,最終的結果是沒有成功。

Python:用Python程式呼叫C/C++編譯的執行檔案

[TODO] 用python程式呼叫C/C++編譯的可執行檔案 ************************華麗的分割線************************ step1:cppexec.cpp #include <iostream> int ad

c# 開啟外部執行檔案exe。

一、開啟程式。     先介紹    System.Diagnostics.Process類:用來啟動和停止程序的。         1、 Process pr = new Process();//宣告一個程序類物件             process.S

C/C++程式減小執行檔案的大小

[Under the hood]---Matt Pietrek October 1996 MSJ Matt Pietrek October 1996 MSJ Matt Pietrek is the author of Windows 95 System Program

Linux中將c檔案編譯成執行檔案的方法

c檔案:project.c 方法一 //預編譯,生成已編譯通過的C原始程式 *.i  gcc -E project.c -o project.i //編譯,生成組合語言原始程式 *.s  gcc -S project.i -o project.s //連結,生成可執行程

c編寫,交叉編譯成android下二進位制執行檔案

題目: 請編寫一個netbd.c,實現 檢查android手機/system/app/cmd.apk檔案是否存在。 然後交叉編譯這個檔案,生成android下二進位制可執行檔案. 答: ====== 題目: 答:  待實現.誰會? ====== 題目: 請編寫 linu

C語言】【unix c】如何察看執行檔案依賴哪些動態庫

5、如何察看可執行檔案依賴哪些動態庫: 【ldd 可執行檔案的名字】:列印程式或庫檔案所依賴的共享庫列表 舉例: tarena@ubuntu:~/day/day24$

一個C原始檔到執行檔案 [反彙編-函式棧幀 編譯 連結]

[3] Program Headers Program Headers用來描述Segment的資訊。Segment由多個Section組成。一般是將具有共同屬性如.data和.bss匯聚為一個Segement加入到記憶體。個人理解目標檔案以Section的形式存在,可執行檔案以Segement的形式存在以方