當前位置:九游会j9娱乐平台-九游ag登录中心网址 » 編程軟體 » 編譯展開

編譯展開-九游会j9娱乐平台

發布時間: 2024-07-06 14:13:19

c語言,說宏展開是在編譯時進行的,啥意思啥叫編譯時進行的

c語言編寫出來的代碼叫源代碼,是供人看的,如果想讓機器執行,需要轉換成機器語言,這個轉換過程就叫編譯。
在c語言中定義的宏,在編譯時,會展開(或叫替換)為實際的語句,如:
#define max 100
void main()
{
int a=max ;
printf("a=%d\n", a );
}
這里max是個宏,當編譯時,這段代碼就會變成:
void main()
{
int a=100; //這里的max會變成100
printf("a=%d\n", a );
}
這就是宏展開、宏替換,然後編譯器,按這樣子的源代碼進行編譯,生成執行程序

❷ c語言文件的編譯與執行的四個階段並分別描述

採納了加我不懂問我 一 c編譯過程概述 目前linux下最常用的c語言編譯器是gcc(gnu compiler collection),它是gnu項目中符合ansi c標準的編譯系統,能夠編譯用c、c 和object c等語言編寫的程序.gcc不僅功能非常強大,結構也異常靈活.最值得稱道的一點就是它可以通過不同的前端模塊來支持各種語言,如java、fortran、pascal、mola-3和ada等. linux系統下的gcc(gnu c compiler)是gnu推出的功能強大、性能優越的多平台編譯器,是gnu的代表作品之一。gcc是可以在多種硬體平台上編譯出可執行程序的超級編譯器,其執行效率與一般的編譯器相比平均效率要高20%~30%。 使用gcc編譯程序時,編譯過程可以被細分為四個階段:
◆ 預處理(pre-processing)
◆ 編譯(compiling)
◆ 匯編(assembling)
◆ 鏈接(linking) 二 編譯過程中各種文件介紹 1.以擴展名區分文件類型.c為後綴的文件,c語言源代碼文件;
.a為後綴的文件,是由目標文件構成的檔案庫文件;
.c,.cc或.cxx 為後綴的文件,是c 源代碼文件;
.h為後綴的文件,是程序所包含的頭文件;
.i 為後綴的文件,是已經預處理過的c源代碼文件;
.ii為後綴的文件,是已經預處理過的c 源代碼文件;
.m為後綴的文件,是objective-c源代碼文件;
.o為後綴的文件,是編譯後的目標文件;
.s為後綴的文件,是匯編語言源代碼文件;
.s為後綴的文件,是經過預編譯的匯編語言源代碼文件。 2.linux目標文件描述 linux 平台下三種主要的可執行文件格式:a.out(assembler and link editor output 匯編器和鏈接編輯器的輸出)、coff(common object file format 通用對象文件格式)、elf(executable and linking format 可執行和鏈接格式)。其中elf是x86 linux系統 下的一種常用目標文件(object file)格式,有三種主要類型: (1)適於連接的可重定位文件(relocatable file),可與其它目標文件一起創建可執行文件和共享目標文件。編譯產生的.o文件就屬於這類。
(2)適於執行的可執行文件(executable file),用於提供程序的進程映像,載入到內存執行。這就是編譯、鏈接之後形成的最終文件。
(3)共享目標文件(shared object file),連接器可將它與其它可重定位文件和共享目標文件連接成其它的目標文件,動態連接器又可將它與可執行文件和其它共享目標文件結合起來創建一個進程映像。這就是庫文件,只指動態庫文件。 詳細了解請看本人收藏的《linux可執行文件分析》 三 編譯過程詳解 c語言的編譯鏈接過程要把我們編寫的一個c程序(源代碼)轉換成可以在硬體上運行的程序(可執行代碼),需要進行編譯和鏈接。編譯就是把文本形式源代碼翻譯為機器語言形式的目標文件的過程。鏈接是把目標文件、操作系統的啟動代碼和用到的庫文件進行組織形成最終生成可執行代碼的過程。過程圖解如下:
從圖上可以看到,整個代碼的編譯過程分為編譯和鏈接兩個過程,編譯對應圖中的大括弧括起的部分,其餘則為鏈接過程。 1. 編譯過程 編譯過程又可以分成兩個階段:編譯和匯編。 1)編譯 編譯是讀取源程序(字元流),對之進行詞法和語法的分析,將高級語言指令轉換為功能等效的匯編代碼,源文件的編譯過程包含兩個主要階段: 第一個階段是預處理階段,在正式的編譯階段之前進行。預處理階段將根據已放置在文件中的預處理指令來修改源文件的內容。如#include指令就是一個預處理指令,它把頭文件的內容添加到.cpp文件中。這個在編譯之前修改源文件的方式提供了很大的靈活性,以適應不同的計算機和操作系統環境的限制。一個環境需要的代碼跟另一個環境所需的代碼可能有所不同,因為可用的硬體或操作系統是不同的。在許多情況下,可以把用於不同環境的代碼放在同一個文件中,再在預處理階段修改代碼,使之適應當前的環境。主要是以下幾方面的處理: (1)宏定義指令, 如 #define a b
對於這種偽指令,預編譯所要做的是將程序中的所有a用b替換,但作為字元串常量的 a則不被替換。還有 #undef,則將取消對某個宏的定義,使以後該串的出現不再被替換。 (2)條件編譯指令, 如#ifdef,#ifndef,#else,#elif,#endif等。
這些偽指令的引入使得程序員可以通過定義不同的宏來決定編譯程序對哪些代碼進行處理。預編譯程序將根據有關的文件,將那些不必要的代碼過濾掉。
(3)頭文件包含指令, 如#include "filename"或者#include 等。 在頭文件中一般用偽指令#define定義了大量的宏(最常見的是字元常量),同時包含有各種外部符號的聲明。採用頭文件的目的主要是為了使某些定義可以供多個不同的c源程序使用。因為在需要用到這些定義的c源程序中,只需加上一條#include語句即可,而不必再在此文件中將這些定義重復一遍。預編譯程序將把頭文件中的定義統統都加入到它所產生的輸出文件中,以供編譯程序對之進行處理。包含到c源程序中的頭文件可以是系統提供的,這些頭文件一般被放在 /usr/include目錄下。在程序中#include它們要使用尖括弧(< >)。另外開發人員也可以定義自己的頭文件,這些文件一般與c源程序放在同一目錄下,此時在#include中要用雙引號("")。
(4)特殊符號,預編譯程序可以識別一些特殊的符號。
例如在源程序中出現的line標識將被解釋為當前行號(十進制數),file則被解釋為當前被編譯的c源程序的名稱。預編譯程序對於在源程序中出現的這些串將用合適的值進行替換。

預編譯程序所完成的基本上是對源程序的「替代」工作。經過此種替代,生成一個沒有宏定義、沒有條件編譯指令、沒有特殊符號的輸出文件。這個文件的含義同沒有經過預處理的源文件是相同的,但內容有所不同。下一步,此輸出文件將作為編譯程序的輸出而被翻譯成為機器指令。

第二個階段編譯、優化階段,經過預編譯得到的輸出文件中,只有常量;如數字、字元串、變數的定義,以及c語言的關鍵字,如main,if,else,for,while,{,}, ,-,*,\等等。

編譯程序所要作得工作就是通過詞法分析和語法分析,在確認所有的指令都符合語法規則之後,將其翻譯成等價的中間代碼表示或匯編代碼。

優化處理是編譯系統中一項比較艱深的技術。它涉及到的問題不僅同編譯技術本身有關,而且同機器的硬體環境也有很大的關系。優化一部分是對中間代碼的優化。這種優化不依賴於具體的計算機。另一種優化則主要針對目標代碼的生成而進行的。

對於前一種優化,主要的工作是刪除公共表達式、循環優化(代碼外提、強度削弱、變換循環控制條件、已知量的合並等)、復寫傳播,以及無用賦值的刪除,等等。 後一種類型的優化同機器的硬體結構密切相關,最主要的是考慮是如何充分利用機器的各個硬體寄存器存放的有關變數的值,以減少對於內存的訪問次數。另外,如何根據機器硬體執行指令的特點(如流水線、risc、cisc、vliw等)而對指令進行一些調整使目標代碼比較短,執行的效率比較高,也是一個重要的研究課題。

2)匯編
匯編實際上指把匯編語言代碼翻譯成目標機器指令的過程。對於被翻譯系統處理的每一個c語言源程序,都將最終經過這一處理而得到相應的目標文件。目標文件中所存放的也就是與源程序等效的目標的機器語言代碼。目標文件由段組成。通常一個目標文件中至少有兩個段:代碼段:該段中所包含的主要是程序的指令。該段一般是可讀和可執行的,但一般卻不可寫。數據段:主要存放程序中要用到的各種全局變數或靜態的數據。一般數據段都是可讀,可寫,可執行的。 2. 鏈接過程 由匯編程序生成的目標文件並不能立即就被執行,其中可能還有許多沒有解決的問題。
例如,某個源文件中的函數可能引用了另一個源文件中定義的某個符號(如變數或者函數調用等);在程序中可能調用了某個庫文件中的函數,等等。所有的這些問題,都需要經鏈接程序的處理方能得以解決。

鏈接程序的主要工作就是將有關的目標文件彼此相連接,也即將在一個文件中引用的符號同該符號在另外一個文件中的定義連接起來,使得所有的這些目標文件成為一個能夠誒操作系統裝入執行的統一整體。

根據開發人員指定的同庫函數的鏈接方式的不同,鏈接處理可分為兩種: (1)靜態鏈接 在這種鏈接方式下,函數的代碼將從其所在地靜態鏈接庫中被拷貝到最終的可執行程序中。這樣該程序在被執行時這些代碼將被裝入到該進程的虛擬地址空間中。靜態鏈接庫實際上是一個目標文件的集合,其中的每個文件含有庫中的一個或者一組相關函數的代碼。 (2)動態鏈接
在此種方式下,函數的代碼被放到稱作是動態鏈接庫或共享對象的某個目標文件中。鏈接程序此時所作的只是在最終的可執行程序中記錄下共享對象的名字以及其它少量的登記信息。在此可執行文件被執行時,動態鏈接庫的全部內容將被映射到運行時相應進程的虛地址空間。動態鏈接程序將根據可執行程序中記錄的信息找到相應的函數代碼。

對於可執行文件中的函數調用,可分別採用動態鏈接或靜態鏈接的方法。使用動態鏈接能夠使最終的可執行文件比較短小,並且當共享對象被多個進程使用時能節約一些內存,因為在內存中只需要保存一份此共享對象的代碼。但並不是使用動態鏈接就一定比使用靜態鏈接要優越。在某些情況下動態鏈接可能帶來一些性能上損害。四 編譯過程實例描述 linux中使用的gcc編譯器把上述的幾個過程集成,一個命令就能完成編譯的整個過程。為了詳細說明每個步驟,下面我們將分部執行。下圖是gcc代理的編譯過程
常式: 在linux下創建文件hello.c,內容如下,
#include
int main(void)
{
printf ("hello,everybody!\n");
return 0;
} ◆ 預處理(pre-processing)
使用-e參數可以讓gcc在預處理結束後停止編譯過程,對應的命令是cpp,
# gcc -e hello.c -o hello.i 用編輯器打開hello.i,可以看到stdio.h文件被展開到了hello.i中。 ◆ 編譯(compiling)
使用-s參數將hello.i編譯為匯編程序,使用的命令是cc -s,
#gcc –s hello.i –o hello.s 用編輯器打開hello.s,顯然已經變成了匯編代碼。 ◆ 匯編(assembling)
使用-c參數將hello.s編譯為目標文件,對應的命令是as,
#gcc –c hello.s –o hello.o 可以利用工具readelf或者objmp讀出hello.o的信息。 ◆ 鏈接(linking) 產生可執行文件,利用命令ld
# gcc hello.o -o hello
利用readelf,可以看到hello.o和hello文件的區別。

❸ c語言的編譯和運行按什麼鍵

編譯f9 運行ctrl f9
不同的編譯器命令快捷鍵略有不同。
下面是visual stdio的命令快捷鍵列表:
ctrl shift b
生成解決方案

ctrl f7
生成編譯

ctrl o
打開文件

ctrl shift o
打開項目

ctrl shift c
顯示類視圖窗口

f4
顯示屬性窗口

shift f4
顯示項目屬性窗口

ctrl shift e
顯示資源視圖

f12
轉到定義

ctrl f12
轉到聲明

ctrl alt j
對象瀏覽

ctrl alt f1
幫助目錄

ctrl f1
動態幫助

f1
幫助

shift f1
當前窗口幫助

ctrl alt f3
幫助-搜索

shift alt enter
全屏顯示

ctrl -
向後定位

ctrl shift -
向前定位

ctrl f4
關閉文檔窗口

ctrl page down
游標定位到窗口上方

ctrl page up
游標定位到窗口下方

ctrl f6
ctrl tab
下一個文檔窗口

ctrl shift f6
ctrl shift tab
上一個文檔窗口

alt f6
下一個面板窗口

ctrl k, ctrl l
取消remark

ctrl k, ctrl c
注釋選擇的代碼

ctrl k, ctrl u
取消對選擇代碼的注釋

ctrl m, ctrl o
折疊代碼定義

ctrl m, ctrl l
展開代碼定義

ctrl delete
刪除至詞尾

ctrl backspace
刪除至詞頭

shift tab
取消製表符

ctrl u
轉小寫

ctrl shift u
轉大寫

ctrl shift end
選擇至文檔末尾

ctrl shift home
選擇至文檔末尾開始

shift end
選擇至行尾

shift home
選擇至行開始處

shift alt end
垂直選擇到最後尾

shift alt home
垂直選擇到最前面

ctrl a
全選

ctrl w
選擇當前單詞

ctrl shift page up
選擇至本頁前面

ctrl shift page down
選擇至本頁後面

ctrl end
文檔定位到最後

ctrl home
文檔定位到最前

ctrl g
轉到…

ctrl k, ctrl p
上一個標簽

ctrl k, ctrl n
下一個標簽

alt f10
調試-applycodechanges

ctrl alt break
停止調試

ctrl shift f9
取消所有斷點

ctrl f9
允許中斷

ctrl shift f5
調試-重新開始

f5
運行調試

ctrl f5
運行不調試

f10
跨過程序執行

f11
單步逐句執行

ctrl j
列出成員

ctrl page down
下一個視圖

ctrl b
格式-粗體

ctrl shift t
格式-文字縮進

❹ 高級語言的編譯過程,經過哪幾個步驟

開發c程序有四個步驟:編輯、編譯、連接和運行。

任何一個體系結構處理器上都可以使用c語言程序,只要該體系結構處理器有相應的c語言編譯器和庫,那麼c源代碼就可以編譯並連接到目標二進制文件上運行。

1、預處理:導入源程序並保存(c文件)。

2、編譯:將源程序轉換為目標文件(obj文件)。

3、鏈接:將目標文件生成為可執行文件(exe文件)。

4、運行:執行,獲取運行結果的exe文件。

(4)編譯展開擴展閱讀:

將c語言代碼分為程序的幾個階段:

1、首先,對源代碼文件進行測試。以及相關的頭文件,比如stdio。h.cpp預處理為。我的文件。預編譯。該文件不包含任何宏定義,因為所有宏都已展開,且包含的文件已插入。我提起。

2、編譯過程是對預處理後的文件進行詞法分析、語法分析、語義分析和優化,生成相應的匯編代碼文件。這個過程通常是整個程序的核心部分,也是最復雜的過程之一。

3、匯編程序不直接輸出可執行文件,而是輸出目標文件。匯編程序可以調用ld來生成可運行的可執行程序。也就是說,您需要鏈接到大量文件以獲得最終可執行文件「a.out」。

4、在鏈接過程中,其他目標文件中定義的函數調用指令需要重新調整,而其他目標文件中定義的變數也存在同樣的問題。

❺ (編譯原理) 求下述文法對應正規式: s->0a|1b a->1s|1 b->0s|0

一、簡單的推導思路
1、該文法的對應正規式為:[01|10]
2、推導:
(1)首先,展開產生式s,可知s要麼以0開頭,要麼以1開頭;
(2)如果s按產生式s->0a展開,則s必以01開頭,因為通過產生式a->1s|1可知,a必定是以1開頭的;
(3)如果s按產生式s->1b展開,則s必以10開頭,因為產生式b必定以0開頭;
(4)綜上,可知,s是以01或10開頭的非終結符號;
(5)當a以產生式a->1展開或 b以b->0展開時,s將推導結束;
(6)當a以產生式a->1s展開或 b以b->0s展開時,產生式中的非終結符號s將重復(1)-(3)的推導步驟;
(7)綜上所述,該文法的對應正規式為:[01|10] 。

二、聯立方程組求解
假設非終結符號s、a、b都分別代表一個正規式,則正規文法的產生式集合所代表的就是關於正規式s、a、b的一個方程組。
我們將文法「|」符號替換為正規式「 」符號,可得,
s=0a 1b=0(1s 1) 1(0s 0)=01(s ε) 10(s ε)=(01 10)(s ε)=(01 10)s (01 10)。
根據方程x=rx t有形如x=r*t的解論斷,可得,
s=(01 10)*(01 10)=[01|10] 。

❻ c語言宏預編譯中如何將字元串展開

ide 是 vsts 2005 / 2008 的話可以查看預編譯文件
項目屬性頁 - 配置屬性 - c / c - 預處理器 - 生成與處理文件 - 是
然後會生成一個後綴名是 .i 的文件,對著 .c .cpp 就可以查看如何展開了。

一般情況下在程序預處理時,一般出現宏名字的地方都用宏定義的字元串替換,然後根據有參數沒有參數進行不同的調用。

熱點內容
resin下jsp不能正常編譯 發布:2024-07-17 16:34:44 瀏覽:229
sqlserver如何切換主備伺服器 發布:2024-07-17 16:23:02 瀏覽:299
mc18伺服器ip 發布:2024-07-17 16:23:02 瀏覽:379
仙境傳說手游腳本 發布:2024-07-17 16:09:24 瀏覽:691
matlab命令窗口和新建腳本 發布:2024-07-17 15:51:26 瀏覽:375
建ftp文件夾 發布:2024-07-17 15:51:26 瀏覽:955
魔獸撿物腳本 發布:2024-07-17 15:27:56 瀏覽:130
開發ip伺服器 發布:2024-07-17 15:24:42 瀏覽:388
安卓系統視頻製作哪個好用 發布:2024-07-17 15:10:47 瀏覽:210
androidapk結構 發布:2024-07-17 15:10:43 瀏覽:945
网站地图