當前位置:首頁 » 編程語言 » c語言有宏為什麼還有函數模板
擴展閱讀
webinf下怎麼引入js 2023-08-31 21:54:13
堡壘機怎麼打開web 2023-08-31 21:54:11

c語言有宏為什麼還有函數模板

發布時間: 2023-06-16 19:16:00

c語言中帶參數的宏定義與函數的區別(試舉例)

宏只是字元的替換,在預處理階段就給替換到代碼中去了比如下面的代碼
#include

#define
MAX(x,
y)
((x)>(y)?(x):y())
int
main()
{
int
a
=
2,
b
=
4;
int
m;
m
=
MAX(2,
4);
printf("%d\n",
m);
return
0;
}
如果你用的是gcc編譯器,執行
gcc
-E
main.c
-o
main.i,打開main.i文件就可以看到他是如何替換進去的,直接拖到最後,前面的都是stdio.h中的內容。
int
main()
{
int
a
=
2,
b
=
4;
int
m;
m
=
((2)>(4)?(2):4());
printf("%d\n",
m);
return
0;
}
函數就不同了,函數還需要分配棧空間,在執行函數時都要進行入棧和出棧操作,有的還需要分配堆空間。
宏所實現的功能有限,而且長代碼不易讀,但是對於邏輯簡單、代碼不長、經常使用的功能由宏來實現是個不錯的選擇

Ⅱ C語言中宏函數跟自定義的函數有什麼區別

可以把宏理解成拼字游戲,它功能很強大,但是強大到使用不好就會有副作用。C++有很多語言設施用來完全特定功能的宏,如const,inline,template,就是為了讓大家少用宏。給你舉個宏和函數不同的例子代碼:
#define max(x,y) ((x)>(y)?(x):(y))
template <class T>
inline T max(T x,T y){return x>y?x:y;}
看起來似乎是相同的功能,可是函數調用,畢竟會求完每一個實參的值,再傳遞給被調函數,即使聲明了inline,在調用點展開而不發生實際的調用開銷。
但是你試試用這個調用宏,結果就會有問題:
int i=4,j=5;
int k=max(i++,j++);
如果是函數調用,i==5,j==6,k==5。如果是宏的話,結果是:
int k=((i++)>(j++)?(i++):(j++));
你覺得會一樣嗎?所以,慎用宏。
MFC中有很多功能是宏完成的,它太強大了,很多情況下有宏很高效,但是不容易控制。

Ⅲ 在c語言中如何實現函數模板

各種用
C
語言實現的模板可能在使用形式上有所不同。現以一個求和函數
Sum
為例,用
C++
Template
可寫如下:
template
R
Sum(const
T
*array,
int
n)
{
R
sum
=
0;
for
(int
i
=
0
;
i
<
n
;
++i)
sum
+=
i;
return
sum;
}
如果不是內置類型,該模板隱式地需要
有R
R::operator+=(T)運算符可用。
1.
使用函數指針作為
Functor
替換者
Typedef
struct
tagAddClass
{
Void
(*add)(char*
r1,
const
char*
r2);
Int
elemSize;
Char
sum[MAX_ELEM_SIZE];
}
AddClass;
void
Sum(AddClass*
self,
const
char*
array,
int
n)
{
for
(int
i
=
0
;
i
<
n
;
++i)
self->add(self->sum,
array
+
i*self->elemSize);
}
使用時:
Void
AddInt(char*
r1,
const
char*
r2)
{
*(long*)r1
+=
*(int*)r2;
}
AddClass
addClass
=
{AddInt,
2,
0
};
Int
array[100];
Read(array);
Sum(&addClass,
array,
100);
…..
2.
用宏作為Functor的替換者
#define
GenSumFun(SumFunName,
Add,
RetType,
ElemType)
RetType
SumFunName
(const
ElemType
*array,
int
n)
\
{
RetType
sum
=
0;
for
(int
i
=
0
;
i
<
n
;
++i)
Add(sum,
i);
return
sum;
}
使用時:
#define
AddInt(x,
y)
((x)
+=
(y))
GenSumFun(SumInt,
AddInt,
long,
int)
…..
Int
array[100];
Read(array);
Long
sum
=
SumInt(array,
100);
…..
3.
所有可替換參數均為宏
至少需要一個額外的文件(實現文件)為
impsum.c
/*
impsum.c
*/
RetType
FunName(const
ElemType
*array,
int
n)
{
RetType
sum
=
0;
for
(int
i
=
0
;
i
<
n
;
++i)
Add(sum,
i);
return
sum;
}
使用時:
#undef
RetType
#undef
FunName
#undef
ElemType
#undef
Add
#define
AddInt(x,
y)
((x)
+=
(y))
#define
RetType
long
#define
FunName
SumInt
#define
ElemType
int
#define
Add
AddInt
#include
impsum.c
…..
Int
array[100];
Read(array);
Long
sum
=
SumInt(array,
100);
4.
總結:
第一種方法,易於跟蹤調試,但是效率低下,適用於對可變函數(函數指針)的效率要求不高,但程序出錯的可能性較大(復雜),模板函數(Sum)本身很復雜,模板參數也比較復雜(add)的場合。
第二種方法,效率高,但很難跟蹤調試,在模板函數和模板參數本身都很復雜的時候更是如此。
第三種方法,是我最近幾天才想出的,我認為是最好的,在模板參數(Add)比較復雜時可以用函數(第二種也可以如此),簡單時可以用宏,並且,易於調試。在模板函數本身很復雜,而模板參數比較簡單時更為優越。但是,可能有點繁瑣。

Ⅳ c語言,宏定義,與函數的差別 我覺得宏定義和函數沒什麼差別啊, 是否可以用宏定義代替函數

首先宏定義和函數是有差別的
宏定義是在編譯之前處理的,不做語法檢查。
這個很危險
另外我要說
#define
a(b,c)
{(b)+(c)}
表示bc之合,在結果上和函數確實一樣

Ⅳ 在c語言中如何實現函數模板

如果要寫個函數支持多種數據類型,首先想到的就是C++的模板了,但是有時候只能用C語言,比如在linux內核開發中,為了減少代碼量,或者是某面試官的要求…
考慮了一陣子後,就想到了qsort上.qsort的函數原型:
void qsort( void *base, size_t num, size_t width, int (__cdecl *compare )(const void *elem1, const void *elem2 ) );
快排時,只要自己實現相應數據類型的比較函數cmpare就可以了.如果比較int型時,一個典型的compare函數如下:

那麼,就是說可以利用void *. void *意指未指定類型,也可以理解為任意類型。其他類型的指針可以直接賦值給void *變數,但是void *變數需要強制類型轉換為其它指針類型。這個相信大家都知道。那麼下面以一個簡單的題目為例,來探討如何在C語言中實現模板函數。
方法1: 利用void *.
在看下面的源程序之前,需要了解幾點。首先,在32位平台上,任何類型的指針所佔的位元組都是4個位元組,因為32位機器虛擬內存一般為4G,即2的32次方,只要32位即4個位元組就可以足夠定址,sizeof(void *)=4; 其次,雖然各種不同類型的指針所佔的空間都為4個位元組,但是不同類型的指針所指的空間的位元組數卻不同(這一點尤為重要,下面的程序我在開始沒有調通就因為這點意識不強)。所以,如果你將一個指針強制轉換為另一個類型的指針,指針本身所佔的位元組是不變的,但是,如果對這個指針進行運算,比如 *p,p++,p-=1等一般都是不同的。 再次,函數指針應該了解下,這里不多說。 最後,因為Sandy跟我說,C++開始的時候模板的實現其實就是利用宏替換,在編譯的時候確定類型。所以,為了方便,類型也用了預編譯指令#define。

<span>#include"stdio.h"</span>

<span>#include"stdlib.h"</span>

<span>//typedefintT;//或者下面的也可以.</span>

<span>#defineTint</span>

//這個FindMin是Sandy寫的.felix021也寫了個,差不多的就不貼出來的.

voidFindMin(constvoid*arr,intarr_size,intarrmembersize,int*index,

int(*cmp)(constvoid*,constvoid*b)){

inti;

*index=0;

char*p=(char*)arr;

char*tmp=p;

for(i=1;i<arr_size;i++){

if(cmp(tmp,p)>0){

tmp=p;

}

p+=arrmembersize;

}

(*index)=((int)(tmp-arr))/arrmembersize;

}

*/</span>

可以把指針看作是char*,如果轉換為int*,那下面的位移就不正確了.</span>

index<span>=</span>i<span>;</span>

<span>}</span>

<span>}</span>

<span>return</span>index<span>;</span>

<span>}</span>

<span>int</span>result<span>;</span><span>//result保存的是最小值索引.</span>

result<span>=</span>FindMin<span>(</span>arr,<span>12</span>,