Linux 版 (精华区)

发信人: netiscpu (夜☆星光点点☆), 信区: Linux
标  题: ◇ 之六 -- 巨集之评析
发信站: 紫 丁 香 (Sun Nov 15 21:53:19 1998), 转信



寄信人: guest.bbs@hgluo.hust.edu.cn 
标  题: ◇ 之六 -- 巨集之评析
发信站: 华南理工大学 BBS木棉站
日  期: Thu Feb 20 14:30:36 1997

       战   斗   世   家   C 语言讲座                  #6

                                 作者: Lgw Lu
                                 E-Mail: lgwlu@ms1.hinet.net
---------------------------------------------------------------

                   < 巨集之评析 >

前言:

     巨集是包括在前端处理器里的一部份,但它重要吗?! 当然非常重
  要!! 以下将让你了解原来巨集有这麽多用途,这麽多陷阱!!

内文:

     巨集功用:

  1. 程式码替换

     大部分懂 C 的人都会,这是最简单的功能,但也是最容易中计的
     陷阱,请看说明....

     EX:

       #define FUNC(a,b) a*b

       以这行看来,感觉没啥问题,也许你的写法也是类似这种,其实
       这行里充满陷阱,WHY ??

       你 CALL 的方式                   结果

       FUNC(5,6)                        5*6   正确!!

       FUNC(X+1,Y+2)                    X+1*Y+2
                                        = X+Y+2  错误!!

       现在了解的吧!! 那要怎麽改??
       改成

       #define FUNC(a,b) (a)*(b)

       这样的话,FUNC(X+1,Y+2) 结果就是我们想要的 (X+1)*(Y+2)
       这样没错了吧!!
       错错错错错错错错错错错错错错错错错错错错错错错错错错错
       为啥还是错??
       请看:

       X/FUNC(Y,Z)  原本是想得到 X/(Y*Z),但结果却是

       X/(Y)*(Z) = (X*Z)/Y 这实在是.......

       正确改法:

       #define FUNC(a,b) ((a)*(b))

       结论:
            (1) 若用 C++,请用 inline function 方式,取代巨集
            (2) 每个变数都必须用 (),最後也要加 (),如本例!!

  2. 多行程式码替换

     大部分人可能不知道巨集可不只一行,所以功能就相对被忽略了!

     EX:

     #define FUNC1(a,b)              #define FUNC2(a,b)
       (a-10)/5; \                    {
       b=a*2; \                       (a-10)/5; \
       a=b;                           b=a*2;  \
                                      a=b;
                                      }

     这两个巨集功用相同,但 FUNC1 却有陷阱,请看

     for(i=0;i<100;i++)
        FUNC1(x[i],y[i]);

     这结果是啥?! 是 (a-10)/5 这行做了 100 次,而 b=a*2; a=b;
     却都只做一次,现在知道为何要加 { } 了吧!!

  3. 资料替换

     当你某部份资料需要常常变动时,就可使用此法,如果可省下欲找
     寻资料,并且不会发生某处未修改到之情况!!

     EX:

     #define COLOR 0x20

     ............
     fun(COLOR,x);
     ......
     if(COLOR >0x10) .....

     .....

     P.S. 虽然可如此用,但我建议还是使用 const 方式,至於原因为
          何,请参考 #1 说明!!

  4. ANSI C 新功能

     ANSI C 比 K&R C 功能多了 # 及 ## ,这部份其实是 #2 的续篇
     在 #2 中说到 ANSI 及 K&R 差异,现在再加上此部份,ANSI C 又
     胜一筹!!

     说明1: 参数前有 #,则用 " " 括住参数,若是参数中有 "  则加上一 \。

     EX:

        原来写法:

        puts("在 C: 下有一 \"TEST.COM\" 档案");

        输出结果: 在 C: 下有一 "TEST.COM" 档案

        改用巨集:

        #define STR(X) #X

        puts(STR(在 C: 下有一 "TEST.COM" 档案));

        你看!! 是不是以後写起来方便多了,且看起来清楚多了!!

     说明2: ## 会将前後两语法单元连接

     EX:

       #define STR(X,Y) #X ## #Y

       puts(STR(This is "A",This is "B"));

       输出结果: This is "A"This is "B"

  其实若是复杂的 Function 尽量不要使用巨集方式,因为太危险了,
  就算用 { } 一样会有危险!!

  EX:
     #define FUNC(X)
        {
        F1(X);
        F2(X);
        }

     程式中若为 FUNC(a--); 其实你是想用 a-- 後的值去 F1() 及
     F2() 中运算,但实际结果却为

     F1(a--);
     F2(a--);   <=== 这行结果是错的,并 a 被减了 2 ,而非 1

  好了!!巨集就说到这!! 总之一句话,用巨集小心点!!!

预告:
     下篇介绍浮点数的使用须知,< 要命的浮点数 >

  P.S. 若各位有啥想知道的,或某篇想知道更深入的话,请来信告诉我
       因为若无任何问题,本讲座将於 #8 做结束!!

---------------------------------------------------------------

                  <<< 本文版权属於作者 >>>
     本文章可自由引用,拷贝,传阅,但需保持本文章之完整性,从标题
  到最後版权宣告,且不能用来做商业用途!!

     若有任何问题,或是错误之处,欢迎来信批评指教!! 谢谢!!



--
m;32m※ 转寄:.华南网木棉站 bbs.gznet.edu.cn.[FROM: mtlab.hit.edu.cn]
--

                              Enjoy Linux!
                          -----It's FREE!-----

※ 来源:.紫 丁 香 bbs.hit.edu.cn.[FROM: mtlab.hit.edu.cn]
[百宝箱] [返回首页] [上级目录] [根目录] [返回顶部] [刷新] [返回]
Powered by KBS BBS 2.0 (http://dev.kcn.cn)
页面执行时间:3.107毫秒