zoukankan      html  css  js  c++  java
  • C++常见问题之二#define使用中的陷阱

    一.使用#define宏应注意的问题

    1.使用宏定义表达式的时候,加括号是一个好习惯

    首先我们来看一段简短的代码,并试着分析其输出

    #include <iostream>
    
    #define  Add(a,b) a+b
    
    int main()
    {
    
    	std::cout<<Add(1,2)*Add(2,3)<<std::endl;
    
    	return 0;
    }


    结果输出:


    很显然,当我们看到这么一段代码的时候,肯定会呲之以鼻,认为这么简单的错误怎么可能发现不了?别急,这还只是开始,下面我们在对上述代码进行改进,便有了下面的代码:

    #include <iostream>
    
    #define  Add1(a,b) (a+b)
    
    #define  Add2(a,b) (a) + (b)
    
    #define  Mul(a,b) (a*b)
    
    int main()
    {
    
    	std::cout<<Add2(1,2)*Add2(2,3)<<std::endl; //理论上应该是 15
    
    	std::cout<<Mul(Add2(1,2),3)<<std::endl;//理论上应该输出 9
    
    
    	system("pause");
    	return 0;
    }
    

    结果输出:


    上述结果表明,即使是整体加上括号或者分别单独加上括号都不能很好的解决问题,最完备的解决方案就是不要吝啬你的括号,用完备的括号完备的保护每一个宏参数,也就是说,针对上述案例,应该这样:

    #define Add(a,b)  ((a)+(b))

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

    2.使用宏的时候,参数不能变化

    首先,照例我们还是来看一段问题代码:

    #include <iostream>
    #define  CUBE(a) ((a)*(a)*(a))
    inline int Cube(int a)
    {
    	return a*a*a;
    }
    int main()
    {
    	int base1 = 2,base2=2;
    	int nCube1 = CUBE(++base1);
    	int nCube2 = Cube(++base2);
    	std::cout<<"nCube1 = "<<nCube1<<std::endl;
    	std::cout<<"nCube2 = "<<nCube2<<std::endl;
    	system("pause");
    	return 0;
    }

    再看一下输出结果:


    其实这样的结果也很好理解,因为宏是单纯的替换,每一次替换都自增了一次,这就是宏在展开时对其参数的多次取值替换所带来的副作用,为避免这种情况,最简单的方法就是保证使用宏的时候参数不能变换。

    3.用大括号将宏所定义的多条表达式括起来

    我们还是来看一段示例:

    #include <iostream>
    
    typedef struct Cube
    {
    	int x;
    	int y;
    	int z;
    };
    
    #define  INITIAL(a,b,c)
    	a=1;
    	b=2;
    	c=3;
    
    int main()
    {
    	int x,y,z;
    
    	INITIAL(x,y,z);
    
    	std::cout<<"x = "<<x<<"  y = "<<y<<"  z = "<<z<<std::endl;//OK  no problem
    
    	
    	Cube  cube[10];
    
    
    	int i=0;
    	for (;i<10;++i)
    		INITIAL(cube[i].x,cube[i].y,cube[i].z);
    	
    
    	for (i=0;i<10;++i)
    		std::cout<<cube[i].x<<"  "<<cube[i].y<<"  "<<cube[i].z<<std::endl;
    	
    
    	system("pause");
    	return 0;
    }

    结果显示:



    其实说来说去还是一个宏替换的范围问题,改正很简单,只要在宏定义的时候加上大括号就行了,其实宏是一个很强大的工具,但是我们在用的时候要格外的小心,千万不要吝啬你的括号




  • 相关阅读:
    高阶函数与匿名函数
    A task in a suit and a tie:paraphrase generation with semantic augmentation解读
    利用tensorboard将数据可视化(tf1.x 和 tf2.x)
    IplImage, CvMat, Mat 的关系
    剑指OFFER之合并两个排序的链表
    整数与字符串的互相转化
    二分查找法
    集成算法
    003-决策树案例
    002-决策树构造实例
  • 原文地址:https://www.cnblogs.com/ainima/p/6331127.html
Copyright © 2011-2022 走看看