欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C語言深入探究程序的編譯之預處理

 更新時間:2022年05月12日 09:14:22   作者:Iceevov  
在C語言的程序中包括各種以符號#開頭的編譯指令,這些指令稱為預處理命令。預處理命令屬于C語言編譯器,而不是C語言的組成部分,通過預處理命令可擴展C語言程序設計的環(huán)境

1.程序的翻譯環(huán)境和執(zhí)行環(huán)境

在ANSI C中任何一種實現(xiàn)中,存在兩個不同的環(huán)境.

第一種是翻譯環(huán)境,在這個環(huán)境中源代碼被轉(zhuǎn)換為可執(zhí)行的機器指令

第二種執(zhí)行環(huán)境,它用于實際執(zhí)行代碼。

2.詳解編譯與鏈接

2.1翻譯環(huán)境

1.組成一個程序的每個源文件通過編譯過程分別轉(zhuǎn)換成目標代碼(object code)。

2.每個目標文件由鏈接器(linker)捆綁在一起,形成一個單一而完整的可執(zhí)行程序。

3.鏈接器同時也會引入標準C函數(shù)庫中任何被該程序所用到的函數(shù),而且它可以搜索程序員個人的程序庫,將其需要的函數(shù)也鏈接到程序中。

2.2編譯本身也分為幾個階段

2.3運行環(huán)境

程序執(zhí)行的過程:

1. 程序必須載入內(nèi)存中。在有操作系統(tǒng)的環(huán)境中:一般這個由操作系統(tǒng)完成。在獨立的環(huán)境中,程序 的載入必須由手工安排,也可能是通過可執(zhí)行代碼置入只讀內(nèi)存來完成。

2. 程序的執(zhí)行便開始。接著便調(diào)用main函數(shù)

3.開始執(zhí)行程序代碼。這個時候程序?qū)⑹褂靡粋€運行時堆棧(stack),存儲函數(shù)的局部變量和返回 地址。程序同時也可以使用靜態(tài)(static)內(nèi)存,存儲于靜態(tài)內(nèi)存中的變量在程序的整個執(zhí)行過程一直保留他們的值。

4. 終止程序。正常終止main函數(shù);也有可能是意外終止

3.預處理詳解

3.1預處理符號

__FILE__//進行編譯的源文件
__LINE__//文件當前的行號
__DATE__//文件被編譯的日期
__TIME__//文件被編譯的時間
__STDC__//如果編譯器遵循ANSI C,其值為1,否則未定義

3.2#define

3.2.1#define定義標識符

//語法
#define name stuff
//舉例
#define MAX 1000
#define reg register //為 register這個關鍵字,創(chuàng)建一個簡短的名字
#define do_forever for(;;) //用更形象的符號來替換一種實現(xiàn)
#define CASE break;case //在寫case語句的時候自動把 break寫上。
// 如果定義的 stuff過長,可以分成幾行寫,除了最后一行外,每行的后面都加一個反斜杠(續(xù)行符)。
#define DEBUG_PRINT printf("file:%s\tline:%d\t \
date:%s\ttime:%s\n" ,\
__FILE__,__LINE__ , \
__DATE__,__TIME__ )

3.2.2#define定義宏

#define 機制包括了一個規(guī)定,允許把參數(shù)替換到文本中,這種實現(xiàn)通常稱為宏(macro)或定義

宏(define macro)。

聲明方式:

#define name( parament-list ) stuff

舉例:

#define ADD(x) x+x
int a = 5;
ADD(a)
//等價于
//ADD(a)=5+5

3.2.3#define的替換規(guī)則

在程序中擴展#define定義符號和宏時,需要涉及幾個步驟。

1. 在調(diào)用宏時,首先對參數(shù)進行檢查,看看是否包含任何由#define定義的符號。如果是,它們首先 被替換。

2. 替換文本隨后被插入到程序中原來文本的位置。對于宏,參數(shù)名被他們的值所替換。

3. 最后,再次對結果文件進行掃描,看看它是否包含任何由#define定義的符號。如果是,就重復上 述處理過程。

注意:

1. 宏參數(shù)和#define 定義中可以出現(xiàn)其他#define定義的符號。但是對于宏,不能出現(xiàn)遞歸。

2. 當預處理器搜索#define定義的符號的時候,字符串常量的內(nèi)容并不被搜索。

3.2.4 宏和函數(shù)對比

宏通常被應用于執(zhí)行簡單的運算。

比如在兩個數(shù)中找出較大的一個。

#define MAX(a, b) ((a)>(b)?(a):(b))

那為什么不用函數(shù)來完成這個任務?

原因有二:

1. 用于調(diào)用函數(shù)和從函數(shù)返回的代碼可能比實際執(zhí)行這個小型計算工作所需要的時間更多。 所以宏比函數(shù)在程序的規(guī)模和速度方面更勝一籌。

2. 更為重要的是函數(shù)的參數(shù)必須聲明為特定的類型。 所以函數(shù)只能在類型合適的表達式上使用。反之這個宏怎可以適用于整形、長整型、浮點型等可以用>來比較的類型。

宏是類型無關的。

宏的缺點:當然和函數(shù)相比宏也有劣勢的地方:

1. 每次使用宏的時候,一份宏定義的代碼將插入到程序中。除非宏比較短,否則可能大幅度增加程序的長度。

2. 宏是沒法調(diào)試的。

3. 宏由于類型無關,也就不夠嚴謹。

4. 宏可能會帶來運算符優(yōu)先級的問題,導致程容易出現(xiàn)錯

宏和函數(shù)的一個對比:

屬性#define定義宏函數(shù)
代碼長度每次使用時,宏代碼都會被插入到程序中。除了非常小的宏之外,程序的長度會大幅度增長函數(shù)代碼只出現(xiàn)于一個地方;每次使用這個函數(shù)時,都調(diào)用那個地方的同一份代碼
執(zhí)行速度更快存在函數(shù)的調(diào)用和返回的額外開銷,所以相對慢一些
操作符優(yōu)先級宏參數(shù)的求值是在所有周圍表達式的上下文環(huán)境里,除非加上括號,否則鄰近操作符的優(yōu)先級可能會產(chǎn)生不可預料的后果,所以建議宏在書寫的時候多些括號。函數(shù)參數(shù)只在函數(shù)調(diào)用的時候求值一次,它的結果值傳遞給函數(shù)。表達式的求值結果更容易預測。
帶有副作用的參數(shù)參數(shù)可能被替換到宏體中的多個位置,所以帶有副作用的參數(shù)求值可能會產(chǎn)生不可預料的結果。函數(shù)參數(shù)只在傳參的時候求值一次,結果更容易控制。
參數(shù)類型宏的參數(shù)與類型無關,只要對參數(shù)的操作是合法的,它就可以使用于任何參數(shù)類型。函數(shù)的參數(shù)是與類型有關的,如果參數(shù)的類型不同,就需要不同的函數(shù),即使他們執(zhí)行的任務是相同的。
調(diào)試宏是不方便調(diào)試的函數(shù)是可以逐語句調(diào)試的
遞歸宏是不能遞歸的函數(shù)是可以遞歸的

3.2.5命名約定

一般來講函數(shù)的宏的使用語法很相似。所以語言本身沒法幫我們區(qū)分二者。

那我們平時的一個習慣是:

把宏名全部大寫

函數(shù)名不要全部大寫

3.3#undef

這條指令用于移除一條宏定義

#undef NAME//如果現(xiàn)存的一個名字需要被重新定義,那么它的舊名字首先要被移除。

3.4條件編譯

在編譯一個程序的時候我們?nèi)绻獙⒁粭l語句(一組語句)編譯或者放棄是很方便的。因為我們有條件編譯指令。

1.
#if 常量表達式
//...
#endif
//常量表達式由預處理器求值。
如:
#define __DEBUG__ 1
#if __DEBUG__
//..
#endif
2.多個分支的條件編譯
#if 常量表達式
//...
#elif 常量表達式
//...
#else
//...
#endif
3.判斷是否被定義
#if defined(symbol)
#ifdef symbol
#if !defined(symbol)
#ifndef symbol
4.嵌套指令
#if defined(OS_UNIX)
#ifdef OPTION1
unix_version_option1();
#endif
#ifdef OPTION2
unix_version_option2();
#endif
#elif defined(OS_MSDOS)
#ifdef OPTION2
msdos_version_option2();
#endif
#endif

到此這篇關于C語言深入探究程序的編譯之預處理的文章就介紹到這了,更多相關C語言預處理內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • C/C++中的static關鍵字詳解

    C/C++中的static關鍵字詳解

    這篇文章主要為大家詳細介紹了 C/C++中的static關鍵字,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2022-03-03
  • 零基礎詳解C語言指針進階

    零基礎詳解C語言指針進階

    在C語言和C++等語言中,數(shù)組元素全為指針變量的數(shù)組稱為指針數(shù)組,指針數(shù)組中的元素都必須具有相同的存儲類型、指向相同數(shù)據(jù)類型的指針變量。指針數(shù)組比較適合用來指向若干個字符串,使字符串處理更加方便、靈活
    2022-02-02
  • C++入門筆記之std::vector容器詳解

    C++入門筆記之std::vector容器詳解

    這篇文章主要給大家介紹了關于C++之std::vector容器的相關資料,vector,一種隨機訪問的數(shù)組類型,它提供了對數(shù)組元素的快速、隨機訪問,以及在序列尾部快速、隨機的插入和刪除操作,需要的朋友可以參考下
    2021-07-07
  • C++實現(xiàn)二叉樹非遞歸遍歷方法實例總結

    C++實現(xiàn)二叉樹非遞歸遍歷方法實例總結

    這篇文章主要介紹了C++實現(xiàn)二叉樹非遞歸遍歷方法實例總結,是算法設計中比較經(jīng)典的一個遍歷算法,需要的朋友可以參考下
    2014-08-08
  • C++教程之a(chǎn)rray數(shù)組使用示例詳解

    C++教程之a(chǎn)rray數(shù)組使用示例詳解

    這篇文章主要為大家介紹了C++教程之a(chǎn)rray數(shù)組使用示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-03-03
  • C語言每日練習之求兩個矩陣的乘積詳解

    C語言每日練習之求兩個矩陣的乘積詳解

    這篇文章主要介紹了如何求兩個矩陣的乘積,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2021-11-11
  • 一文掌握 C++ 智能指針的使用方法

    一文掌握 C++ 智能指針的使用方法

    C++11 引入了智能指針的概念,使用了引用計數(shù)的想法,讓程序員不再需要關心手動釋放內(nèi)存。關于C++指針得內(nèi)容下面文章將為大家做一個詳細介紹
    2021-09-09
  • C++11中的chrono庫詳解

    C++11中的chrono庫詳解

    C++11提供了日期時間相關的庫chrono,通過chrono庫可以很方便的處理日期和時間,這篇文章主要介紹了C++11中的chrono庫,需要的朋友可以參考下
    2023-03-03
  • C語言中文件處理全攻略詳解

    C語言中文件處理全攻略詳解

    這篇文章主要為大家詳細介紹了C語言中文件處理的相關知識,包括創(chuàng)建、寫入、追加操作解析,文中的示例代碼講解詳細,感興趣的小伙伴可以了解一下
    2024-01-01
  • 快速了解Boost.Asio 的多線程模型

    快速了解Boost.Asio 的多線程模型

    這篇文章主要介紹了Boost.Asio 的多線程模型的相關知識,文中代碼非常詳細,供大家參考和學習,感興趣的朋友可以了解下
    2020-06-06

最新評論