iT邦幫忙

DAY 15
1

21世紀C語言實作及感想系列 第 15

21世紀C語言之15 :巨集的困惑

  • 分享至 

  • xImage
  •  

巨集,大陸用語是宏,巨和宏都有macro的意思。

而這些句子都在編譯前處理,所以是前置處理(preprocess), 一枝獨立的程式CPP做這段,所以CPP是前置處理器(preprocessor).

本書的作者,舉出了一些令人困惑的巨集例子。加深讀者對寫正確巨集的印象。

#include <stdio.h>

#define double(x) 2*x
int
main (void)
{


printf ("double is %d \n",double(1+1)*8);
printf ("double is %d \n",double(3+2)*8);

return 0;
}
-----------------------------------------------
gcc -E macro06.c , 可以看前置處理結果
# 3 "macro06.c" 2


int
main (void)
{


2*1+1*8;
2*3+2*8;

return 0;
}

所以會得到

$ ./macro06
double is 10
double is 22

可能和原來要兩倍的意思不一樣,

當程式修改一下,把**#define double(x) 2*(x),**就可以得到兩倍的結果了

這經驗告訴user,巨集加括號是重要的。

第二個例子告訴你,加括號()是正確的,但有時效果看你想的不一樣。不過還是要加括號。

#include <stdio.h>

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

int
main (void)
{

int x=1, y=2; 
int m=max(x, y++);
printf ("y is %d \n",y );
printf ("Max is %d \n",m );

return 0;
}
----------------------------------------
巨集展開:
# 3 "macro07.c" 2



int
main (void)
{

int x=1, y=2;
int m=((x) > (y++) ? (x) : (y++))
printf ("Max is %d \n",m );

return 0;
}
執行結果:
$ ./macro07
y is 4
Max is 3

這個結果,非常有意思。除了巨集外,還有其他令人困惑之處。

下一個例子,是多行巨集的疑惑,記得多行時,最好加個大括號{}

#include <stdio.h>

#define doubleincrement(a, b)\
(a)++;\
(b)++;

int
main (void)
{

int x=1, y=2; 
if (x<y)
doubleincrement(x, y);

printf ("x is %d \n",x );
printf ("y is %d \n",y );

return 0;
}
------------------------------------------
巨集展開:
int
main (void)
{

int x=1, y=2;
if (x<y)
(x)++;(y)++;;

printf ("x is %d \n",x );
printf ("y is %d \n",y );

return 0;





<u><strong>(y)++;; </strong></u>多了一個分號

可是編譯還是會通過,執行結果也沒問題。不過程式可能被理解成

if (x<y)
   (x)++;

(y)++;





(y)++;沒有在if(x<y)裏。這樣也不是原來想的意思,所以多行的巨集,最好<u><strong>加上{}</strong></u>

最後是超好用的技巧,巨集中的#,可以讓user少打很多字,

#include <stdio.h>
#define Peval(cmd) printf(#cmd ": %g\n", cmd);
int main(){
double *plist = (double[]){1, 2, 3};
double list[] = {1, 2, 3};
Peval(sizeof(plist)/(sizeof(double)+0.0));
Peval(sizeof(list)/(sizeof(double)+0.0));
}

----------------------------------------
執行結果
$ ./macro10
sizeof(plist)/(sizeof(double)+0.0): 0.5
sizeof(list)/(sizeof(double)+0.0): 3

把一長串的句子,直接變成字串。很實用的printf 輸出技巧。

上一篇
21世紀C語言之14 :C 標準庫 ,依表頭檔(.h)分類
下一篇
21世紀C語言之16 :用asprintf來改善sprintf
系列文
21世紀C語言實作及感想30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言