zoukankan      html  css  js  c++  java
  • #define的里里外外你知多少

    宏定义(#define)的作用及使用方法属于C语言基础的范畴,本文不打算多做赘述,在此只是给出#define可能引起的或潜在的风险,希望对你有所帮助。

      先看这个宏定义

      1 #define MAX(A, B) (A > B ? A : B)

      这个宏做一个加法的运算,你觉得它有什么问题吗??看看如下的调用会发生什么情况

      1 int a = MAX(2, 1) + 3;

      这里就有情况了,由于运算符的优先顺序不同,那么这里并不能得到我们期望的值。好的,我们可以这样解决

      1 #define MAX(A, B) (A > B ? A : B)    // 加个括号来预防上面的问题

      好,上面的问题现在解决了, 再看看下面的代码

      int i = 0;

      int j = 2;

      int a = MAX(i++, j++);

      现在新的问题又出现了,这段代码还是不能得到我们期望的结果,可能你会说这么用的人有病吗,干吗传这么个参数,但是实际项目中的代码各式各样,出现一次就是麻烦是不是。由于这个问题,因此在C++里建议用inline函数代替宏定义,但是无论如何在C语言的项目里宏定义是非常广泛的存在的,了解一些宏的负面作用还是有助于你写出预防性的代码。

      下面我们再看看#define的另外一个可能的缺陷,先看这个代码

      1 #define TEST_MACRO() \

      2     DO_A(); \

      3     DO_B();

      直接使用这个宏会有问题吗,假设我们如下使用它

      1 if (something)

      2    TEST_MACRO();

      它就会扩展成这样

      1 if (something)

      2    DO_A();

      3    DO_B();

      这样DO_B()原本是有条件的执行,现在是任何时候都无条件执行,视编译器而定,有的编译器能解决这种问题,但是单从C语言语法本身的角度来讲这样就有问题,依赖于编译器来解决问题是有风险的。也许你想用括号{}来解决问题,变成这样

      #define TEST_MACRO() { \

      DO_A(); \

      DO_B(); \

      }

      好,上面的问题解决了,但是如果这样定义宏并且如下使用呢:

      代码

      #define TEST_MACRO() { \

      if (A) \

      DO_A(); \

      else \

      DO_B(); \

      }

      如下使用

      if (...)

      TEST_MACRO();

      else

      {

      ...

      }

      宏展开后:

      if (...) { \

      if (A) \

      DO_A(); \

      else \

      DO_B(); \

      };

      else

      {

      ...

      }

      扩展后第二个 else 前边多了一个分号,编译都不能通过,这其实是好的情况,因为你可以把问题扼杀在编译阶段,如果编译通过但是程序跑出奇怪的行为那才是痛苦。因此关于宏定义就有了do{} while(0)的使用方法

      1 #define TEST_MACRO() do{ \

      2 if (true) \

      3   DO_A(); \

      4 else \

      5   DO_B(); \

      6 }while(0)

      使用do{} while(0) 方法就是为了类似的宏可以在任何时候使用,总之宏定义正反作用都有并且在C++中是不推荐使用的(C++中建议用const定义常量、用inline定义函数),但是在C语言的项目中宏是大量存在的,不过程序终究是人写的,还是看人怎么去用它

  • 相关阅读:
    IE6兼容问题
    清除浮动的几种方法
    CSS的继承性和层叠性
    CSS基础选择器复习
    梦与醒,进与退
    CSS的入门概念
    HTML的入门概念
    弹性布局整理
    点击评论加入输入框(笔记)
    css命名(笔记)
  • 原文地址:https://www.cnblogs.com/linyawen/p/2479134.html
Copyright © 2011-2022 走看看