日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

程序的编译和链接过程

發(fā)布時間:2023/11/27 生活经验 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 程序的编译和链接过程 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
一.虛擬機、linux簡介 簡單介紹一下虛擬機還有就是各種操作系統(tǒng),比如centos,Ubuntu 操作系統(tǒng):linux(centos、Ubuntu、redhat),Android,Windows(xp、win8、win10) 進程,多個程序,分時技術(shù),并行技術(shù) 一次打開多個程序,我們在只有一個cpu,如何讓這些程序進行執(zhí)行呢,看起來好像是在同時進行的,實際上是一個程序執(zhí)行了一點點時間,然后保存執(zhí)行的一些信息,接下來回來再次執(zhí)行,這樣就達到了看上去是多個程序在同時執(zhí)行的效果 操作系統(tǒng)的作用:控制程序的執(zhí)行,管理系統(tǒng)的資源
二.程序的編譯鏈接過程
2.1首先看一下預(yù)處理的指令

關(guān)于上面的預(yù)處理指令,大家可以自己測試一下
(測試例子)(注意是兩行) ANSI 標準 C 定義的幾個宏如下,大家可以簡單的了解一下 __LINE__ 表示正在編譯的文件的行號 __FILE__ 表示正在編譯的文件的名字 __DATE__ 表示編譯時刻的日期字符串,例如: "25 Dec 2007" __TIME__ 表示編譯時刻的時間字符串,例如: "12:30:55" __STDC__ 判斷該文件是不是定義成標準 C 程序
2.2宏定義 編譯器在預(yù)處理的時候,就會把宏定義的數(shù)據(jù)替換成它的元身,這里我們必須了解什么是宏,宏的主要的用法 2.2.1 定義宏常量 #define PI 3.14159265358979323846264338327 比如我們經(jīng)常使用的一個變量,如果這個變量的數(shù)值改變了之后,我們不需要再文件里面一個一個找,而是只需要把宏改變就可以了 #define ERROR_TEST -1 比如我們在test文件中,一些代碼的地方需要使用return -1,或者是exit(-1) 然后有很多類型的錯誤返回,如果每次返回的是-1,-2,-3之類的,一會就把自己給繞暈了 2.2.2定義字符串常量 #define PATH "c/file/linux" 這個一般用在表示文件的路徑的情況下有很多 (大家下去看一下,如果是一行寫不下怎么辦呢,就是比如一行太長了怎么辦) 2.2.3 定義注釋 #define ZZ // 因為在程序編譯的時候,注釋是先于宏處理的 2.2.4 定義表達式(宏函數(shù)) #define MUL(x) x*x 純文本替換 測試用例 MUL(5);MUL(1+2); --- 加上括號MUL((x)*(x)) MUL(5*3)*MUL(5*3) --- 大括號???不要吝嗇括號 2.2.5 空格 #define MUL (x) ((x)*(x)) 比如上面的宏函數(shù),我們要是定義成下面的這個樣子又是什么樣的呢 2.2.6#undef 撤銷宏定義 比如 #define PI 3.14159265358979323846264338327 ... ... ... #undef PI此時PI不在有效了 2.2.7定義宏函數(shù)補充 比如下面的程序 #define PRINTF printf("測試");
這個時候我們可以編寫 一個if esle語句 if(0) PRINTF; else printf("haha\n");
宏函數(shù)比普通函數(shù)的一些特性在哪里 (1)普通的函數(shù)需要建立棧幀,開銷較大,宏函數(shù)在效率上面更勝一籌 (2)函數(shù)中的參數(shù)必須使用特定的類型,換句話說,宏函數(shù)對參數(shù)是不進行類型檢查的,宏函數(shù)是不類型限制的
宏函數(shù)的缺點 宏函數(shù)每次是進行的代碼的替換,有時候可能會增加代碼的長度,使維護起來非常的復(fù)雜 宏函數(shù)的參數(shù)不能是一個類型
2.3. 條件編譯 第一種形式: #ifdef 標識符 程序段 1 #else 程序段 2 #endif 它的功能是,如果標識符已被 #define 命令定義過則對程序段 1 進行編譯;否則對程序段 2 進行編譯。
第二種形式 #ifndef 標識符程序段 1 #else 程序段 2 #endif
第三種形式 #if 常量表達式 程序段 1 #else 程序段 2 #endif

2.4. 文件包含 文件包含是預(yù)處理的一個重要功能,它可用來把多個源文件連接成一個源文件進行編譯,結(jié)果將生成一個目標文件。C語言提供#include 命令來實現(xiàn)文件包含的操作,它實際是宏替換的延伸,有兩種格式: #include<filename> #include"filename" 2.5.#pragma 預(yù)處理 自己上網(wǎng)調(diào)研,寫博客,寫測試用例 #pragma once #pragma warning #pragma pack--這個是張晨亮學長給你們講過的,設(shè)置內(nèi)置內(nèi)存對齊數(shù)

2.6詳解程序編譯和鏈接過程 程序的編譯和鏈接的過程 我們在linux下使用gcc編譯器直接對程序進行編譯,比如使用gcc test.c,然后就會生成一個程序叫做test.out 但是上面的看似簡單的過程實際上是經(jīng)歷了四個階段 預(yù)處理,編譯,匯編,連接 每個過程都有自己要完成的任務(wù)



記住一些操作,ESc對應(yīng)的是iso,
2.6.1. 預(yù)處理 通過預(yù)處理生成一個.i的文件,使用的指令是 gcc -E test.c -o test.i (G) 預(yù)處理過程主要處理的是1. 以#開始的預(yù)處理指令(保留#pragma)2.刪除所有的注釋3.添加文件名和行號,具體的過程如下
  • 將所有的#define刪除,展開所有的宏定義
  • 處理所有的條件預(yù)編譯指令,比如#if,#ifdef....
  • 處理所有的#include預(yù)編譯指令,將所有被包含的文件包含至本文件中來
  • 刪除所有的注釋,//和/* */等
  • 保留所有的#pragma預(yù)處理指令,因為下面還要用到它
2.6.2.編譯 gcc -S test.i -o test.s 作用:將預(yù)處理后的文件,進行一系列的詞法分析,語法分析,語義分析及優(yōu)化后生成相應(yīng)的匯編代碼(這里我們就可以寫一個錯誤的語句來示范一下) 2.6.3. 匯編 gcc -c test.s -o test.o 將匯編代碼解釋成編譯器可以執(zhí)行的二進制代碼 :%!xxd 2.6.4. 鏈接 gcc -o test.o test 這里我們有一個疑問,不是說上面的匯編已經(jīng)將程序變成了二進制代碼了,為什么還要鏈接呢,鏈接是咋鏈接呢,和誰戀呢,戀啥呢 講述一下編寫程序發(fā)展的歷史,一開始是程序員是機器碼,就是一個一個的紙條上面的01代碼,但是這種代碼太晦澀難懂了,于是出現(xiàn)了匯編語言,匯編語言出現(xiàn)之后的一個很大的問題就是,代碼的數(shù)量大大的增加了,這就使得維護代碼起來比較復(fù)雜,于是人們?yōu)榱吮阌诰S護,又想起把代碼分成不同的模塊,每個模塊負責不同的作用,就比如一個頭文件是專門處理圖片的,一個頭文件是專門處理音頻,這樣就產(chǎn)生了不同的模塊,這些模塊之間存在著不同的調(diào)用的過程,然后就是要把不同的分開的模塊組裝起來就是鏈接的過程。 人們將每個源代碼模塊獨立的編譯,然后將編譯后的模塊按照他們的需求組裝起來就是鏈接的過程。 發(fā)給大家一篇PDF《靜態(tài)庫和動態(tài)庫》

推薦書目:《程序員的自我修養(yǎng)--鏈接、裝載與庫》 《C語言深度剖析》

























總結(jié)

以上是生活随笔為你收集整理的程序的编译和链接过程的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。