宏替換是在程序編譯時進行
㈠ 宏替換,宏展開到底分別在什麼時候進行
//在宏 使用的時候 分為
宏定義 和 宏展開, 你那個 宏替換就是展開
宏定義是你自己寫的 #define
然後展開在預編譯時候處理
這個時候編譯器先掃描一遍文件 把用到宏的地方都做字元替換
比如
#define M 1
int a = M;
那麼預編譯的時候就把 M 替換成1
注意宏只做文本替換,所以
比如 #define MUL(__x__, __y__) __x__ * __y__
int a = MUL(a + b, c+ d);
會被替換成 int a = a + b * c + d // 可能就會和初衷違背(如果你想做的是 (a + b) * (c + b))
從展開的角度來說 因為宏是可以嵌套的 所以宏在替換的時候 我們叫做展開
比如 做一個函數參數聲明
#define PARAMS_SET_1(__type__, __name__) __type__ __name__
#define PARAMS_SET_2(__type__, __name__) __type__ __name__##1, __type__ __name__##2
//... 定義N個 PARAMS_SET_N
#define PARAMS(__size__, __type__, __name__) PARAMS_SET_##__size__(__type__, __name__)
然後 定義函數
int foo(PARAMS(2, int, n));
那麼預編譯的時候宏會這樣展開
1, int foo(PARAMS_SET_2(int, n));
2, int foo(int n1, int n2);
另外注意就是編程的時候 由於宏只是文本替換,缺少類型檢測 以及運算順序這樣的功能,所以要少用宏
上面所有的宏都有替換的方案
#define M 1 替換方案
struct M
{enum {value = 1} };
int a = M::value;
#define MUL(__x__, __y__) __x__ * __y__ 替換方案
template<int x, int y>
struct MUL
{enum{value = x * y}};
int a = MUL<10 + 20, 10 + 30>::value;
最後一個PARAMS的替換方案就是函數重載
template<typename T>
int foo(T n1);
template<typename T>
int foo(T n1, Tn2);
//後面定義N個
㈡ 計算機編譯系統對宏定義在編譯時進行語法檢查這句話為什麼錯
第一步被換為area=a*b。
宏定義末尾不加分號,減少輸入錯誤和便於修改。宏替換在編譯前進行,不做表達式求解函數調用在編譯後程序運行時進行,只佔編譯時間。
除了一般的字元串替換,函數調用不會。
宏展開不佔運行時間,不分配內存。
宏的啞實結合不存在類型,作用域為其後的程序,還要做參數代換。
格式:數組大小常用宏定義。
預處理是在編譯之前的處理。
宏定義又稱為宏代換;
",利用宏則可以設法得到多個值。
宏展開使源程序變長。
函數只有一個返回值,預處理不做語法檢查。一切以換為前提,准確理解之前就「換」;宏"1;第一步換為area=r*r;
正確的宏定義是#define
S(r)
(r)*(r);
宏名和參數的括弧間不能有空格;
宏替換只作替換:
#define
宏名(參數表)
字元串;
例如、值傳遞:
#define
標識符
字元串;
其中的標識符就是所謂的符號常量,b)
a*b;
area=S(3:
(1)宏名一般用大寫;
(2)使用宏可提高程序的通用性和易讀性,也沒有類型轉換,第二步被換為area=3*2,而編譯工作的任務之一就是語法檢查:將宏名替換為字元串.帶參數的宏、做任何事情之前先要換,並且分配內存。
預處理(預編譯)工作也叫做宏展開;中永遠不包含宏。
(3)宏定義不分配內存;
(4)宏定義寫在函數的花括弧外邊;
,不做計算:
#define
PI
3,第二步被換為area=a+b*a+b:
(5)實參如果是表達式容易出問題:
#define
S(r)
r*r
area=S(a+b)。
即在對相關命令或語句的含義和功能作具體分析之前就要換;
類似於函數調用。
格式.1415926。
把程序中出現的PI全部換成3。
(6)可以用#undef命令終止宏定義的作用域。
(7)宏定義可以嵌套。
(8)字元串",變數定義分配內存,通常在文件的最開頭。1415926說明,也稱為「宏名」,簡稱「宏」、宏替換。
㈢ 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宏定義在什麼時候替換
1 作用時間不同。 宏定義在編譯期間即會使用並替換,而全局變數要到運行時才可以。 2 本質類型不同。 宏定義的只是一段字元,在編譯的時候被替換到引用的位置。在運行中是沒有宏定義的概念的。
㈤ 宏替換是在程序編譯時完成的,不佔用程序運行時間
是正確的,編譯時預處理,不分配內存空間
㈥ C語言中,下面有關宏替換的敘述中,不正確的是
宏替換是在預編譯時完成的,預編譯的功能是將頭文件引入,並且將定義的宏按字面完成「傻瓜」式替換(即將符合宏的樣式的字元串,替換成宏定義的字元串),宏名沒有類型區分,它只是個字元串。因此,D是錯的
㈦ C語言中宏替換占不佔用運行時間
1.
宏替換不佔用運行時間。宏替換是在編譯時,編譯器完成的。佔用編譯時間。
2.
編譯時,編譯器會將代碼中的宏用對應定義好的代碼進行直接替換,然後再對源代碼進行編譯。
3.
所以宏比函數在運行時更快,因為它不用像函數調用時,要對現有數據進行入棧保存,運行完後,在出棧恢復;它是直接編譯好的代碼。
㈧ C語言:(1)宏替換有數據類型的限制嗎(2)宏調用筆函數調用耗費時間嗎
(1)沒有類型限制,宏替換只是單純代碼文本的替換,不會檢測類型。
(2)所謂「宏調用」實際上是在編譯階段將代碼替換,在編譯完成之後,程序執行時,不存在宏調用的步驟,函數調用是在程序執行時實際調用的,兩者沒有可比性。
㈨ C語言的編譯系統對宏命令的處理是
前言:宏實質就是編譯器在對代碼進行編譯之前進行的一個「查找替換」工作,就跟你在處理文檔時用wps/word/記事本等進行「查找替換」操作一樣。
c語言的編譯系統對宏命令的處理是()
a。在程序運行時進行的
b。在對源程序中其他成分正式編譯之前進行的
c。在程序連續時進行的
d。和c程序中的其他語句同時進行編譯
答:選b。在對源程序中其他成分正式編譯之前進行的
2,
#define
n
2
/*
在預編譯時將用下面代碼中n替換成2
*/
#define
m
n+1
/*
在預編譯時將m替換成n+1(即2+1,n會再被替換成2)*/
#define
num
2*m+1
/*
如上:在預編譯時num替換成2*m+1,即2*n+1+1,即2*2+1+1*/
main()
{int
i;
for(i=1;i<=num;i++)printf("%d\n",i);
/*
*
如上所述,上句展開為:for(i=1;i<=2*2+1+1;i++)printf("%d\n",i);
*
所以:循環將執行6次
*/
}
/*
切記注意:每一個宏百進行替換時只是替換「正文」中的內容,而不包括預編譯語句的內容,
否則就會像不少人理解的那樣,錯誤地認為第2個題中的循環將執行7次
*/
㈩ C語言中,宏替換的替換規則
簡單來說:宏定義又稱為宏代換、宏替換,簡稱「宏」。宏替換是C/C++的預處理中的一部分,在C++標准中有4條規則來定義替換。
規則1:實參替換。
本條規則描述帶參數的宏的替換過程。
對於宏定義中的形參,在替換列表中,如果不是作為#或##的操作數,那麼將對應實參完全
展開(相當於對實參進行求值),然後將替換列表中的形參替換掉.如果是#或##的操作數,
那麼不進行替換。
規則2:多次掃描。
在所有的形參替換為實參後,對結果進行再次掃描,如果發現還有可替換的宏,則進行替換,
否則中止。
規則3:遞歸替換抑制。
如果在替換列表中發現當前正在展開的宏的名字,那麼這里不進行替換.更進一步,在嵌套
的替換過程中發現已經替換過的宏的名字,則不進行替換。
規則4:遞歸預處理抑制。
如果替換後的結果形成預處理指令,則不執行這條預處理指令。
看幾個C++標准中的例子:
#define x 3
#define f(a) f(x * (a))
#undef x
#define x 2
#define g f
#define z z[0]
#define h g(~
#define m(a) a(w)
#define w 0,1
#define t(a) a
f(y+1) + f(f(z)) % t(t(g)(0) + t)(1);
g(x+(3,4)-w) | h 5) & m(f)^m(m);
其結果分別是
f(2 * (y+1)) + f(2 * (f(2 * (z[0])))) % f(2 * (0)) + t(1);
f(2 * (2+(3,4)-0,1)) | f(2 * ( ~ 5)) & f(2 * (0,1))^m(0,1);
對於第一個,主要在於t(t(g)(0) + t)(1)的展開。
容易計算出最外層的t的實參是f(2 * (0)) + t,而作為t的參數傳入時其中的t是
正在被展開的宏,所以根據規則3,不對這個t進行處理,保持不變,得到f(2 * (0)) + t(1)。
對於第二個,h 5)被替換為g(~5),應用規則2,被替換為f(2 * ( ~ 5))。
而m(m)首先被替換為m(w),然後應用規則2再次進行替換,但是m已經是替換過的了,所以保持
不變,只對w進行替換。
#define str(s) # s
#define xstr(s) str(s)
#define debug(s, t) printf("x" # s "= %d, x" # t "= %s",
x ## s, x ## t)
#define INCFILE(n) vers ## n /* from previous #include example */
#define glue(a, b) a ## b
#define xglue(a, b) glue(a, b)
#define HIGHLOW "hello"
#define LOW LOW ", world"
debug(1, 2);
fputs(str(strncmp("abc d", "abc", 』4』) /* this goes away */
== 0) str(: @ ), s);
#include xstr(INCFILE(2).h)
glue(HIGH, LOW);
xglue(HIGH, LOW)
其結果分別是
printf("x" "1" "= %d, x" "2" "= %s", x1, x2);
fputs("strncmp("abc\0d", "abc", 』\4』) = = 0" ": @ ", s);
#include "vers2.h"
"hello";
"hello" ", world"
關鍵是glue和xglue.
對於glue(HIGH, LOW),首先有一個規則1的抑制,得到HIGHLOW;的結果,然後二次掃描,得到
"hello";
對於xglue(HIGH, LOW)沒有抑制效果,所以對參數求值,分別得到HIGH和LOW ", world",即
glue(HIGH, LOW ", world")。
然後進行連接操作得到HIGHLOW ", world",最後再掃描一次得到"hello" ", world"
如果考慮字元串的自然的連接,就可以得到"hello, world"了。
(10)宏替換是在程序編譯時進行擴展閱讀
宏語言是一類編程語言,其全部或多數計算是由擴展宏完成的。宏語言並未在通用編程中廣泛使用,但在文本處理程序中應用普遍。例如, C preprocessor C預處理器Internet Macros(iOpus) M4(如前所述,源於AT&T,捆綁於Unix)
宏定義
c程序提供的預處理功能之一。包括帶參數的宏定義和不帶參數的宏定義。具體是指用一個指定的標志符來進行簡單的字元串替換或者進行闡述替換。形式為:
#define標志符[(參數表)] 字元串
宏名
在上定義中的標志符被稱為「宏名」。
宏展開
在c程序編譯時將宏名替換成字元串的過程稱為「宏展開」。
宏語言是一類編程語言,其全部或多數計算是由擴展宏完成的。宏語言並未在通用編程中廣泛使用, 但在文本處理程序中應用普遍。例如,
C preprocessorC 預處理器
Internet Macros(iOpus)
M4(如前所述,源於AT&T,捆綁於Unix)