c語言巨集定義問題巨集定義不是可以實現和函式相同功能那為什麼還要分函式和巨集定義兩種功能

2021-03-27 12:52:15 字數 5187 閱讀 4003

1樓:物理公司的

我們以下面兩行**為例,描述:

函式式巨集定義:#define max(a,b) ((a)>(b)?(a):(b))

普通函式 :max(a,b)

(1)函式式巨集定義的引數沒有型別,前處理器只負責做形式上的替換,而不做引數型別檢查,所以傳參時要格外小心。

(2)呼叫真正函式的**和呼叫函式式巨集定義的**編譯生成的指令不同。

如果max是個普通函式,那麼它的函式體return a > b ? a : b; 要編譯生成指令,**中出現的每次呼叫也要編譯生成傳參指令和call指令。

而如果max是個函式式巨集定義,這個巨集定義本身倒不必編譯生成指令,但是**中出現的每次呼叫編譯生成的指令都相當於一個函式體,而不是簡單的幾條傳參指令和call指令。所以,使用函式式巨集定義編譯生成的目標檔案會比較大。

(3)函式式巨集定義要注意格式,尤其是括號。

如果上面的函式式巨集定義寫成 #define max(a, b) (a>b?a:b),省去內層括號,則巨集就成了k = (i&0x0f>j&0x0f?

i&0x0f:j&0x0f),運算的優先順序就錯了。同樣道理,這個巨集定義的外層括號也是不能省的。

若函式中是巨集替換為 ++max(a,b),則巨集就成了 ++(a)>(b)?(a):(b),運算優先順序也是錯了。

(4)若函式引數為表示式,則普通函式的呼叫與函式式巨集定義的替換過程是不一樣的。

普通函式呼叫時先求實參表示式的值再傳給形參,如果實參表示式有side effect,那麼這些sideeffect只發生一次。例如max(++a, ++b),如果max是普通函式,a和b只增加一次。但如果max函式式巨集定義,則要成k = ((++a)>(++b)?

(++a):(++b)),a和b就不一定是增加一次還是兩次了。所以若引數是表示式,替換函式式巨集定義時一定要仔細看好。

5)函式式巨集定義往往會導致較低的**執行效率。

看下面一段**:

複製****如下:

int a=;

int max(n)

int main()

若是普通函式,則通過遞迴,可取的最大值,時間複雜度為o(n)。但若是函式式巨集定義,則巨集為( a[n]>max(n-1)?a[n]:

max(n-1) ),其中max(n-1)被呼叫了兩遍,這樣依此遞迴下去,時間複雜度會很高。

儘管函式式巨集定義和普通函式相比有很多缺點,但只要小心使用還是會顯著提高**的執行效率,畢竟省去了分配和釋放棧幀、傳參、傳返回值等一系列工作,因此那些簡短並且被頻繁呼叫的函式經常用函式式巨集定義來代替實現。

2樓:龔煒林

現在的教科書啊, c語言的標準定義,是不包括巨集的。

巨集是編譯器的一部分,我們通常寫**,為了**高可用等,一般離不開使用巨集。

巨集定義是編譯器的前處理器處理的,真正編譯的時候,才是解析具體的語言語法,

具體巨集定義的使用,還得看編譯器的支援了。

巨集只有一個特徵:就是字串替換。前處理器處理巨集的時候,就是把**中的巨集,替換為巨集代表的字串,至於加的一些#if #else的邏輯,也是可以理解為替換。

巨集定義不能實現和函式的相同功能,函式可以劃分域,會佔用棧,可以做介面,高複用**。

而巨集就不一樣了,純粹替換字串, 不能劃分域,那你只用巨集,就會整個檔案都在同一個作用域,定義一個變數,其它巨集還不能隨便重名... ...

再比如,我寫一個函式,編譯之後,只佔4k空間,然後,這個函式被10000處呼叫,但是仍然只需要4k空間來儲存函式**,如果你換成巨集,每一處呼叫都會佔用4k空間的(因為是字串替換),所以,會引起實際佔用4k * 10000 = ? ,拿作業系統不用執行了

就按照上邊的區別去想,自然解答了你這個問題。

c語言在函式內定義巨集有什麼壞處嗎?

3樓:匿名使用者

巨集定義巨集定義是c提供的三種預處理功能的其中一種,這三種預處理包括:巨集定義、檔案包含、條件編譯

編輯本段1.不帶引數的巨集定義:

巨集定義又稱為巨集代換、巨集替換,簡稱「巨集」。

格式:#define 識別符號 字串

其中的識別符號就是所謂的符號常量,也稱為「巨集名」。

預處理(預編譯)工作也叫做巨集:將巨集名替換為字串。

掌握"巨集"概念的關鍵是「換」。一切以換為前提、做任何事情之前先要換,準確理解之前就要「換」。

即在對相關命令或語句的含義和功能作具體分析之前就要換:

例: #define pi 3.1415926

把程式中出現的pi全部換成3.1415926

說明:(1)巨集名一般用大寫

(2)使用巨集可提高程式的通用性和易讀性,減少不一致性,減少輸入錯誤和便於修改。例如:陣列大小常用巨集定義

(3)預處理是在編譯之前的處理,而編譯工作的任務之一就是語法檢查,預處理不做語法檢查。

(4)巨集定義末尾不加分號;

(5)巨集定義寫在函式的花括號外邊,作用域為其後的程式,通常在檔案的最開頭。

(6)可以用#undef命令終止巨集定義的作用域

(7)巨集定義可以巢狀

(8)字串" "中永遠不包含巨集

(9)巨集定義不分配記憶體,變數定義分配記憶體。

編輯本段2.帶引數的巨集定義:

除了一般的字串替換,還要做引數代換

格式:#define 巨集名(參數列) 字串

例如:#define s(a,b) a*b

area=s(3,2);第一步被換為area=a*b; ,第二步被換為area=3*2;

類似於函式呼叫,有一個啞實結合的過程:

(1)實參如果是表示式容易出問題

#define s(r) r*r

area=s(a+b);第一步換為area=r*r;,第二步被換為area=a+b*a+b;

正確的巨集定義是#define s(r) ((r)*(r))

(2)巨集名和引數的括號間不能有空格

(3)巨集替換隻作替換,不做計算,不做表示式求解

(4)函式呼叫在編譯後程式執行時進行,並且分配記憶體。巨集替換在編譯前進行,不分配記憶體

(5)巨集的啞實結合不存在型別,也沒有型別轉換。

(6)函式只有一個返回值,利用巨集則可以設法得到多個值

(7)巨集使源程式變長,函式呼叫不會

(8)巨集不佔執行時間,只佔編譯時間,函式呼叫佔執行時間(分配記憶體、保留現場、值傳遞、返回值

c語言巨集定義技巧(常用巨集定義)

寫好c語言,漂亮的巨集定義很重要,使用巨集定義可以防止出錯,提高可移植性,可讀性,方便性 等等。下面列舉一些成熟軟體中常用得巨集定義。。。。。。

4樓:王8888好

巨集定義在函式內部和定義在函式外部的效果是一樣的。好像沒有什麼好壞之分,可能是程式設計習慣的問題。

5樓:姐狠愛你別想賴

巨集定義寫在函式內部主要是為了方便,巨集定義是預處理的,並沒什麼壞處

6樓:匿名使用者

巨集定義定義在函式中,可以限制巨集定義的適用範圍。

c語言巨集定義如何用?用巨集定義有什麼優點?

7樓:我愛流雨飛軒

巨集定義巨集定義是c提供的三種預處理功能的其中一種,這三種預處理包括:巨集定義、檔案包含、條件編譯

編輯本段1.不帶引數的巨集定義:

巨集定義又稱為巨集代換、巨集替換,簡稱「巨集」。

格式:#define 識別符號 字串

其中的識別符號就是所謂的符號常量,也稱為「巨集名」。

預處理(預編譯)工作也叫做巨集:將巨集名替換為字串。

掌握"巨集"概念的關鍵是「換」。一切以換為前提、做任何事情之前先要換,準確理解之前就要「換」。

即在對相關命令或語句的含義和功能作具體分析之前就要換:

例: #define pi 3.1415926

把程式中出現的pi全部換成3.1415926

說明:(1)巨集名一般用大寫

(2)使用巨集可提高程式的通用性和易讀性,減少不一致性,減少輸入錯誤和便於修改。例如:陣列大小常用巨集定義

(3)預處理是在編譯之前的處理,而編譯工作的任務之一就是語法檢查,預處理不做語法檢查。

(4)巨集定義末尾不加分號;

(5)巨集定義寫在函式的花括號外邊,作用域為其後的程式,通常在檔案的最開頭。

(6)可以用#undef命令終止巨集定義的作用域

(7)巨集定義可以巢狀

(8)字串" "中永遠不包含巨集

(9)巨集定義不分配記憶體,變數定義分配記憶體。

編輯本段2.帶引數的巨集定義:

除了一般的字串替換,還要做引數代換

格式:#define 巨集名(參數列) 字串

例如:#define s(a,b) a*b

area=s(3,2);第一步被換為area=a*b; ,第二步被換為area=3*2;

類似於函式呼叫,有一個啞實結合的過程:

(1)實參如果是表示式容易出問題

#define s(r) r*r

area=s(a+b);第一步換為area=r*r;,第二步被換為area=a+b*a+b;

正確的巨集定義是#define s(r) ((r)*(r))

(2)巨集名和引數的括號間不能有空格

(3)巨集替換隻作替換,不做計算,不做表示式求解

(4)函式呼叫在編譯後程式執行時進行,並且分配記憶體。巨集替換在編譯前進行,不分配記憶體

(5)巨集的啞實結合不存在型別,也沒有型別轉換。

(6)函式只有一個返回值,利用巨集則可以設法得到多個值

(7)巨集使源程式變長,函式呼叫不會

(8)巨集不佔執行時間,只佔編譯時間,函式呼叫佔執行時間(分配記憶體、保留現場、值傳遞、返回值

c語言巨集定義技巧(常用巨集定義)

寫好c語言,漂亮的巨集定義很重要,使用巨集定義可以防止出錯,提高可移植性,可讀性,方便性 等等。下面列舉一些成熟軟體中常用得巨集定義。。。。。。

8樓:匿名使用者

主要用於函式重定義,通用性,可以用一個變數符號替代另一個變數符號格式:#define m(x,y) x+y在主程式裡寫入z=m(6,9);等價於z=6+9;而寫成z=(6-8,9);等價於z=6-8+9 ;直接代入

還有就是 :#define uint unsigned int 即用 uint 代替unsigned int 便於書寫,還有就是不同作業系統的通用變數識別

9樓:匿名使用者

用#define 來定義,如#define max 100

優點:在以後的程式中 要修改max的大小 不用跑到程式中找 直接修改

#define max 的大小即可。很方便。

c語言怎麼巨集定義2維陣列C語言怎麼巨集定義一個2維陣列

如果要強調是二維陣列,這樣也許更合適些 c c code?define m 80 define n 100 define array a,m,n a m n char array 1 例如 define m 80 define n 100 define array a,m,n a m n char ...

C語言關於巨集定義的習題,C語言中關於巨集定義的一道計算題

fudgf 5 x 等價於 2.84 y x,此時y 5,x 2 故結果為 2.84 5 2 12.84 轉為整型即為12,你理解錯了,如果將 define fudgf y 2.84 y 定義成 define fudgf y 2.84 y 這樣算出來的結果即為15 define fudgf y 2....

巨集定義與直接賦值有什麼區別,C語言中巨集定義的10和直接定義1有什麼區別

巨集定義 定義的是常量符號。直接賦值,賦給的是變數符號。巨集定義是預處理是完成的,本質是字元替換 直接賦值是記憶體上的操作版,與執行時有關 權 include define iii int int main void 想這個c語言 中,巨集定義iii,那麼它的下面就可以用iii來代表int,在編譯處...