zoukankan      html  css  js  c++  java
  • 宏定义#define整理

    一、宏定义#define 

    优点:一方面可以节省程序的空间上的篇幅,另外,恰当地使用宏定义可提高程序的时间效率。代码可以写的通俗易懂。可以提高程序的清晰性、可读性,使于修改移植等。

    缺点:宏定义的使用实际上也存在副作用,大量的使用会破坏程序的可读性,并给程序的调试带来麻烦,是优点也是缺点。过多的宏定义,代码不容易调试,代码进不去宏定义当前所运行的内容。

    一般来说,如果一个函数非常大,一般不宜采用宏定义来进行改造,仅仅是那些小的函数,而且非常影响效率的函数才值得这样去做。

    1. 不带参宏定义

    例如: #define MAX  1000

     (1)宏名一般用大写

      (2)使用宏可提高程序的通用性和易读性,减少不一致性,减少输入错误和便于修改。例如:数组大小常用宏定义

      (3)预处理是在编译之前的处理,而编译工作的任务之一就是语法检查,预处理不做语法检查。

      (4)宏定义末尾不加分号;

      (5)宏定义写在函数的花括号外边,作用域为其后的程序,通常在文件的最开头。

      (6)可以用#undef命令终止宏定义的作用域

      (7)宏定义可以嵌套

      (8)字符串" "中永远不包含宏

    2.带参的宏定义

    例如:#define ADD(x,y) ((x)+(y))

    1)实参如果是表达式容易出问题

      #define S(r) r*r

      area=S(a+b);第一步换为area=r*r;,第二步被换为area=a+b*a+b;

      正确的宏定义是#define S(r) (r)*(r)

      (2)宏名和参数的括号间不能有空格

      (3)宏替换只作替换,不做计算,不做表达式求解

      (4)函数调用在编译后程序运行时进行,并且分配内存。宏替换在编译前进行,不分配内存

      (5)宏的哑实结合不存在类型,也没有类型转换。

      (6)函数只有一个返回值,利用宏则可以设法得到多个值

      (7)宏展开使源程序变长,函数调用不会

      (8)宏展开不占运行时间,只占编译时间,函数调用占运行时间(分配内存、保留现场、值传递、返回值)

       (9)宏定义不分配内存,变量定义分配内存。宏替换发生的过程 

    二、 宏展开过程

    为了理解#define的作用,让我们来了解一下对C语言源程序的处理过程。当我们在一个集成的开发环境如Turbo C中将编写好的源程序进行编译时,实际经过了预处理、编译、汇编和连接几个过程,见图。 


        图1     C语言的编译过程 

    三、预处理器功能

    其中预处理器产生编译器的输出,它实现以下的功能: 
    (1)    文件包含 
    可以把源程序中的#include 扩展为文件正文,即把包含的.h文件找到并展开到#include 所在处。 
    (2)    条件编译 
    预处理器根据#if和#ifdef等编译命令及其后的条件,将源程序中的某部分包含进来或排除在外,通常把排除在外的语句转换成空行。 
    (3)    宏展开 
    预处理器将源程序文件中出现的对宏的引用展开成相应的宏 定义,即本文所说的#define的功能,由预处理器来完成。 
    经过预处理器处理的源程序与之前的源程序有所有不同,在这个阶段所进行的工作只是纯粹的替换与展开,没有任何计算功能,所以在学习#define命令时只要能真正理解这一点,这样才不会对此命令引起误解并误用。 

    四、样例贴代码

    // 直接替换

    #define  max   1000

     

    // ##的使用,##链接,#把字符变为字符串

    #define  test(classname,len,type)

        char*  unit_test_binary_to_geometry_service_pid = "pj."#classname#len#type"id";

     

    #define  str(x)   #x

     

    // 返回一个字符

    #define getch(c) #@c

     

    // 定义一个某类型的变量名称。

    #define cat(x,y) x##y

     

     

    void  main()

    {

        string str_ =  str(waht);

        char* tmp_cat = "this is a test";

        string cat(var,1235);

        var1235 = tmp_cat;

        char ch_ = ch(t);

        test(A,12,int)

        string temp = unit_test_pid;    

    }

     

    自己的用例:

    #define  unit_test_marco_derived_start(test_class_name,test_class_service_name,test_class_service_pid)

    test_class_service_name *          ___##test_class_service_name;

    void test_unit_module (unit_test_writer::ptr test_writer_);

    static char*  unit_test_##test_class_service_pid = "rw.unit.test."#test_class_name;

    class  unit_test_##test_class_name

        :public  unit_test

    {

    public:

        typedef rw_shared_ptr< unit_test_##test_class_name > ptr;

        typedef rw_shared_ptr<const unit_test_##test_class_name > const_ptr;

        

        unit_test_##test_class_name (unit_test_service* test_service_,runtime* runtime_)

            : _unit_test_service( test_service_ )

            , _runtime( runtime_ )

        {

            ___##test_class_service_name = ( test_class_service_name * ) _runtime->get_service( test_class_service_pid )->get_service();

        }

        virtual ~ unit_test_##test_class_name (){}

        

        virtual void test(unit_test_result::ptr test_result_, unit_test_writer::ptr test_writer_)

        {

            test_writer_->write("  -----------------start to test "#test_class_name"...--------------------- ");

            test_unit_module (test_writer_);

            test_writer_->write("  -----------------end to test "#test_class_name"...--------------------- ");

            return;

        }

    private:

        unit_test_service*                 _unit_test_service;

        runtime*                           _runtime;

    private:

     };

    当然宏定义的用法不止这么点,多种多样。

    五、预处理命令

    对于预处理命令,还有很多。也把别人的贴出来供各位参考:

      宏定义不分配内存,变量定义分配内存。宏替换发生的过程 
    预处理命令由#(hash字符)开头, 它独占一行, #之前只能是空白符. 以#开头的语句就是预处理命令, 不以#开头的语句为C中的代码行. 常用的预处理命令如下:

    #define              定义一个预处理宏
    #undef               取消宏的定义

    #include            包含文件命令
    #include_next   与#include相似, 但它有着特殊的用途

    #if                      编译预处理中的条件命令, 相当于C语法中的if语句
    #ifdef                判断某个宏是否被定义, 若已定义, 执行随后的语句
    #ifndef             与#ifdef相反, 判断某个宏是否未被定义
    #elif                  若#if, #ifdef, #ifndef或前面的#elif条件不满足, 则执行#elif之后的语句, 相当于C语法中的else-if
    #else                与#if, #ifdef, #ifndef对应, 若这些条件不满足, 则执行#else之后的语句, 相当于C语法中的else
    #endif              #if, #ifdef, #ifndef这些条件命令的结束标志.
    defined            与#if, #elif配合使用, 判断某个宏是否被定义

    #line                标志该语句所在的行号
    #                      将宏参数替代为以参数值为内容的字符窜常量
    ##                   将两个相邻的标记(token)连接为一个单独的标记
    #pragma        说明编译器信息

    #warning       显示编译警告信息
    #error            显示编译错误信息

    说明:近期用了一些宏定义,所以就抽空整理了网上的部分东西。

    若有问题,请随时联系!

  • 相关阅读:
    单例模式
    建造者模式
    工厂模式
    八大排序算法之插入排序
    八大排序算法之基数排序
    lua 4 使用table实现其他数据结构,并介绍遍历方法
    lua 3 循环
    lua 2 变量
    lua 1 基本语法和注意事项
    template指针小测试
  • 原文地址:https://www.cnblogs.com/qitian1/p/6461983.html
Copyright © 2011-2022 走看看