1.什麼是巨集定義?
巨集(macro),是一種批量處理的稱謂。電腦科學裡的巨集是一種抽象(abstraction),它根據一系列預定義的規則替換一定的文字模式。直譯器或編譯器在遇到巨集時會自動進行這一模式替換。對於編譯語言,巨集展開在編譯時發生,進行巨集展開的工具常被稱為巨集展開器。巨集這一術語也常常被用於許多類似的環境中,它們是源自巨集展開的概念,這包括鍵盤巨集和巨集語言。絕大多數情況下,「巨集」這個詞的使用暗示著將小命令或動作轉化為一系列指令。
巨集定義:是指用乙個巨集名(名字)來代表乙個字串。巨集定義的功能是在編譯預處理時,對程式中所有出現的「巨集名」都用巨集定義中的字串去代換,這稱為「巨集代換」或「巨集展開」。
2.巨集應用
1).巨集定義常量
#define pi 3.1415926
#define path "d:\project\src"
2).巨集定義表示式
#define max(a,b) ((a)<(b)?(b):(a))
注意:巨集定義僅是做簡單的文字替換,如果是表示式需要用括號括起來,否則可能會出現邏輯上的「錯誤」
如下會得到意想不到的結果:
#include#define sum(x, y) x + y //正確寫法是:#define sum(x, y) ((x) + (y))
int main()
巨集定義換行表示式(交換兩個整數值)#define swap(x, y) \
注意:巨集定義行連線符是』\』
3.巨集定義運用的好處與缺點
巨集定義的好處:
1).提高**的可讀性,方便進行修改;
2).巨集定義是簡單的文字替換,使用帶參的巨集定義完成函式呼叫,可以提高程式的執行效率,減少系統開銷。
分析:巨集是在預處理階段進行巨集替換的,執行時不需要轉換,占用編譯時間。並且巨集定義不進行記憶體分配,由變數定義分配記憶體。(巨集定義不存在型別問題,引數也是無型別的)
函式呼叫是在編譯後,程式執行時進行的,需要分配記憶體,值傳遞,返回值等一系列操作,占用執行時間。
3).巨集是由預處理器處理的,通過字串操作可以完成很多編譯器無法實現的功能。比如##連線符。
巨集定義缺點:
1).對帶參的巨集而言,由於是直接替換,並不會檢查引數是否合法,存在安全隱患。
2).不方便除錯問題。
4.什麼是條件編譯?
—般情況下,c語言源程式中的每一行**.都要參加編譯。但有時候出於對程式**優化的考慮.希望只對其中一部分內容進行編譯.此時就需要在程式中加上條件,讓編譯器只對滿足條件的**進行編譯,將不滿足條件的**捨棄,這就是條件編譯(conditional compile)。
5.條件編譯應用
三種語法格式:
1).if格式
#if 表示式
條件語句1
#else
條件語句2
#endif
當表示式的值為真時,編譯條件語句1,否則編譯條件語句2。分支#else和條件語句2可以沒有。
2).ifdef格式
#ifdef 識別符號
條件語句1
#else
條件語句2
#endif
當識別符號已被定義時(用#define定義),編譯條件語句1,否則編譯條件語句2。分支#else和條件語句2可以沒有。
3).ifndef格式
#ifndef 識別符號
條件語句1
#else
條件語句2
#endif
和ifdef格式相反(if not def)
6.#if(表示式)、#if defined(識別符號) 和 #ifdef (識別符號) 的區別
1).#if(表示式)後面跟的是表示式,條件為真時,把條件語句編譯進去。
2).#if defined(識別符號)後面跟的是巨集定義,不管巨集定義的識別符號是真還是假,只要存在就把條件語句編譯進去。
3).#ifdef(識別符號)和第二個用法一樣,但是只能用於單個識別符號,作為判斷依據。
注意:如果是多個巨集定義識別符號作為判斷依據,只能用defined()。
如:
#if (deined(a) || defined(b))
條件語句1
#endif
7.綜合引用
1).防止乙個標頭檔案被重複包含
#ifndef _hello_h
#define _hello_h
#include#includeint main();
#endif
當頭檔案第一次被包含時,正常處理,符號_hello_h被定義為1。如果標頭檔案被再次包含,通過條件編譯,它的內容被忽略。符號_hello_h按照被包含標頭檔案的檔名進行取名,以避免由於其他標頭檔案使用相同的符號而引起的衝突。
注意:預處理器仍將整個標頭檔案讀入,即使這個標頭檔案所有內容將被忽略。這種處理將託慢編譯速度,如果可能,應該避免出現多重包含。
#ifndef的是方式是受c/c++語言標準支援。#ifndef方式依賴於巨集名稱要唯一。
優點:可以保證同乙個檔案不會被包含多次,也能保證內容完全相同的兩個檔案不會被同時包含。
缺點:如果不同標頭檔案中的巨集名不小心」碰撞」,可能就會導致你看到標頭檔案明明存在,編譯器卻硬說找不到宣告的狀況。由於編譯器每次都需要開啟標頭檔案才能判定是否有重複定義,因此在編譯大型專案時,#ifndef會使得編譯時間相對較長。
另外一種處理方式#pragma once
#pragma once
#include#includeint main();
#pragma once由編譯器提供保證:
同乙個檔名不會被包含多次。無法對乙個標頭檔案中的一段**作#pragma once宣告,只能針對檔案。
優點:不會出現巨集名一樣引發的奇怪問題,大型專案的編譯速度也因此得以提高。
缺點:如果某個標頭檔案有多份拷貝,此方法不能保證它們不被重複包含。在c/c++中,#pragma once是乙個非標準但是被廣泛支援的方式。
注意:相容性不好,較老編譯器不支援這種方式,如gcc 3.4版本之前不支援#pragma once
巨集定義 C語言基礎學習筆記
define include ifndef define maxszie 10000帶引數的巨集 define add x,y x y define plus x,y add x,y define add x,y x y 呼叫 plus plus a,b c 呼叫結果 就是按照順序巢狀 最終 c b...
C語言基礎學習筆記 巨集
巨集定義 define用來定義乙個識別符號和乙個字串,用這個識別符號替代這個字串。1.不帶引數的巨集定義 define 巨集名 字串 表示這是一條預處理命令 巨集名,是乙個識別符號,要符合識別符號的命名規則,並要求大寫 字串的位置可以是常量 表示式 格式字串 注意 巨集定義不是語句,不需要在末尾加分...
C語言程式設計 學習筆記 巨集定義
編譯預處理指令 開頭的是編譯預處理指令 它們不是c語言的成分,但是c語言程式離不開它們 define用來定義乙個巨集 如 define pi 3.14159這樣pi這個東西就是3.14159的值 在編譯過程中,計算機會把 中出現的pi全部換成3.14159 也可以有如下定義 define forma...