精华内容
下载资源
问答
  • 宏定义函数
    万次阅读
    2019-04-13 15:45:48

    在看OpenFoam源码的时候突然看到TypeName(“xxx”);这句几乎每个类都有,一开始以为是TypeName(“xxx”)调用构造函数,细看不太对,应该是调用宏定义的函数,这个宏函数原型在$SRC/OpenFOAM/db/typeInfo文件里定义的。

    如下:

    #define TypeName(TypeNameString)       \
         ClassName(TypeNameString);          \
     virtual const word& type() const {return typeName;} 

    官方注释是:声明了ClassName()用一个纯虚类型的info

    ClassName()呢本身也是一个宏定义函数,看一下它的定义

    #define ClassName(TypeNameString)       \
     classNameNoDebug(TypeNameString);       \
     static int debug

    对于ClassName(),官方注释和解释是:add typeName information from argument TypeNameString to a class.

    also declares debug information

    首先理解宏定义到底是什么,最简单的当然是

    #define a 10
    #define b a

    宏定义是一种简单的语义替换。

    它在元编程时有两种风格,如下所示

    //第一种,这里identifier是宏的名字,replacement-list是零个或多个标记序列,
    //后继的程序文本中所有出现的identifier的地方都会被预处理器展开为相应的replacemen-list
    #define identifier replacement-list
    //第二种,类似函数的宏,好比"预处理阶段的元函数”
    //定义方式如下
    #define identifier(a1,a2,...an) replacement-list
    

    在第二种类似函数的宏定义中,其中每一个ai标识符都命名了一个宏形参(macro parameter),当宏名字出现在后继的程序文本中并且后跟合适的实参列表时(argument list),它将被扩充为replacement-list,而且其中每个出现参数的地方都会被替换为用户给出的实参。[1]

    综上所述,对于TypeName和ClassName这两个宏,(刚好都是三行),第一行就是identifier,第二行第三行都是它的displacement-list,宏在多行的时候需要用\来连接。(这一点和shell编程很像)

    【1】C++模板元编程 David abrahams Aleksey Gurtovoy等 荣耀译

    更多相关内容
  • 要写好C语言,漂亮的宏定义是非常重要的。宏定义可以帮助我们防止出错,提高代码的可移植性和可读性等。
  • 宏定义函数

    千次阅读 2020-08-29 18:56:39
    概念 在预编译阶段完成代码替换。 优势 (1)增加代码的可读性: 宏定义的优点很多,但我个人理解宏定义最明显的优点...宏定义函数的参数没有数据类型,因此可轻松实现模板函数的功能 #define MAX(a, b) (a > b ? a

    概念

    在预编译阶段完成代码替换。

    优势

    (1)增加代码的可读性:

    宏定义的优点很多,但我个人理解宏定义最明显的优点就是增加代码的可读性。求圆的面积, 用“PI * r* r”比 “3.14r”的可读性就强很多了。

    #define PI 3.14
    
    float circleArea(float r) {
      return PI * r * r;
    }
    

    (2)自带“模版函数”的buff:

    宏定义函数的参数没有数据类型,因此可轻松实现模板函数的功能

    #define MAX(a, b) (a > b ? a : b)
    
    std::cout << "max of a and b is: " << MAX(1, 2)  << std::endl;
    std::cout << "max of a and b is: " << MAX(1.5, 2.1) << std::endl;
    

    (3)相比于正常函数,宏定义函数性能更快

    宏定义的本质决定了这个优势,宏定义只是在代码编译阶段做一个简单的替换,没有任何语法和优化的空间,因此宏定义函数没有正常函数所需的开销,包括:开辟空间,记录返回地址,形参压栈,从函数中返回释放堆栈。

    缺点#define SUM(a,b) a+b

    • 1 宏定义函数只能完成一些简单的替换,因此他的使用场景是有限制的,即使是宏定义函数, 也只是完成简单的功能, 不能真正的替代函数。
    • 2 由于只是做一个替换,因此使用的时候需要谨慎,避免出现符号优先级而出现的低级错误。
    #define SUM(a,b) a+b
    std::cout << "area of rectangle: " << 2 * SUM(1, 2) << std::endl;
    // 打印的结果是4, 而不是6.因此替换后的代码:
    2 * 1 + 2, 而不是2 *1+ 2

    一个惯用的用法

    用do{}while(0)包裹宏定义函数中的代码,这样的好处就是方便实现很复杂的宏定义函数,还可以把这个宏定义函数伪装成一个正常的函数去执行。
    如下例:

    #define UNIT_AREA(shape)               \
      do {                                 \
        if (shape == "circle") {           \
          std::cout << PI << std::endl;    \
        } else if ( shape == "square") {   \
          std::cout << "1" << std::endl;   \
        } else {                           \
          std::cout << "1.0" << std::endl; \
        }                                  \
      } while(0)
     
     std::cout << "area of unit area: " << std::endl;
     UNIT_AREA("circle");
    

    宏定义函数中的特殊符号

    (1) …和__VA__ARGS__

    支持宏定义就函数中的可变参数,宏定义参数可变,或者部分参数可变。
    使用“…”配合“VA_ARGS”。

    #define  LOG(...) {printf("%s\n", __VA_ARGS__);}
    #define  ERROR_LOG(x, ...) if (x) {printf("%s\n", __VA_ARGS__);}
    
    // 以下代码皆可执行
     LOG("this is log")
     LOG("this is log");
     ERROR_LOG(1, "this is error log");
     {printf("log");}
     {printf("log");};
    

    连接符:##

    待写

    展开全文
  • 文章目录为什么要使用宏函数?什么是宏如何使用宏宏的定义不带参数的宏带参数的宏(假参数,不是真正的参数,只是替换而已)原理 为什么要使用宏函数? 在C程序中,可以用宏代码提高...参考文章:为什么要用宏定义函数

    为什么要使用宏函数?

    在C程序中,可以用宏代码提高执行效率。宏代码本身不是函数,但使用起来象函数。
    预处理器用复制宏代码的方式代替函数调用,省去了参数压栈、生成汇编语言的CALL调用、
    返回参数、执行return等过程,从而提高了速度。 (避免函数调用,提高程序效率)
    使用宏代码最大的缺点是容易出错,预处理器在复制宏代码时常常产生意想不到的边际效应。
    参考文章:为什么要用宏定义函数

    什么是宏

    它是一种预处理器指令,在预编译阶段将宏名替换为后面的替换体 。

    如何使用宏

    宏的定义

      #define       WIDTH             960
      预处理指令		宏名       	替换体(多行可用 \ 延续) 
    

    不带参数的宏

    #include <stdio.h>
    #include <stdlib.h> 
    
    #define _width 1024 //宏命名规则同变量名 
    #define ADDR "中华人民共和国云南\
     省飞天县" 
    
    int main(void){ 
    	printf("width: %d\n", _width); 
    	printf("我的祖籍: %s\n", ADDR);
    	
    	system("pause"); 
    	return 0; 
    }
    

    VS上运行结果:

    width: 1024
    我的祖籍: 中华人民共和国云南 省飞天县
    

    带参数的宏(假参数,不是真正的参数,只是替换而已)

    #include <stdio.h>
    #include <stdlib.h> 
    
    #define SQUARE(x) x*x  
    
    int main(void) {
    	int i = 10;
    	int j = SQUARE(i); // 宏展开 j = i*i;
    	int k = SQUARE(8 + 2); // 宏展开 8+2*8+2
    
    	printf("j: %d\n", j);
    	printf("k: %d\n", k);
    
    	system("pause");
    	return 0;
    }
    

    运行结果:

    j: 100
    k: 26
    

    毋庸置疑,j = 100;但 k = 26,为啥?
    宏只是一个替换,不会自动加括号,非常死板!

    解决方法:

    #define SQUARE(x) ((x)*(x))  
    
    #include <stdio.h>
    #include <stdlib.h> 
    
    #define SQUARE(x) ((x)*(x))  
    
    int main(void) {
    	int i = 10;
    	int j = SQUARE(i); // 宏展开 j = i*i;
    	int k = SQUARE(8 + 2); // 宏展开 8+2*8+2
    
    	printf("j: %d\n", j);
    	printf("k: %d\n", k);
    
    	system("pause");
    	return 0;
    }
    

    运行结果:

    j: 100
    k: 100
    

    原理

    这里可以知道,使用宏比调用函数更加高效。因为,使用宏就像使用头文件一样,就比如使用<string.h>,使用头文件<string.h>进行预编译之后,直接可以使用字符串进行定义使用;宏也是如此,在定义宏之后,编译器直接进行了预编译,这时候调用它,就是直接进行替换。

    而调用其他函数时,要给他在内存中单独分配空间,普通变量分布在栈区,动态内存分布在堆区,静态变量在全局数据区(全局数据区也包括全局变量),字符常量在常量区,二进制指令(也就是函数体)分布在代码区。执行这个函数时,要获取被调用函数指定的地址(被调用函数的地址有一个范围,起始地址就是函数的入口地址,被调用函数从起始地址开始一步步往下执行),之后程序会跳转到被调函数的第一条语句,一步步往下依次执行被调函数中的语句,直到函数执行结束。

    参考文章:宏的定义,使用,以及使用宏为什么比调用函数更加高效

    对了,如果宏函数与函数名称相同,优先使用宏定义函数

    #include <stdio.h>
    // div function prototype
    float div(float, float);
    #define div(x, y) x / y
    
    int main()
    {
    // use of macro div
    // Note: %0.2f for taking two decimal value after point
    printf("%0.2f", div(10.0, 5.0));
    // removing defined macro div
    #undef div
    // function div is called as macro definition is removed
    printf("\n%0.2f", div(10.0, 5.0));
    return 0;
    }
    
    // div function definition
    float div(float x, float y) { return y / x; }
    

    编译运行结果:

    2.00
    0.50
    

    参考文章:C 中关于宏和预处理器的有趣事实

    展开全文
  • 若字符串是表达式,我们称之为函数宏定义,那函数宏定义与普通函数有什么区别呢?我们以下面两行代码为例,展开描述:函数宏定义:#define MAX(a,b) ((a)>(b)?(a):(b))普通函数 :MAX(a,b) { return a>b?a:b;}...
  • C语言:宏定义函数

    万次阅读 多人点赞 2019-03-18 11:40:46
    通过一个比较函数的例子来说明宏函数和普通函数的区别: 宏函数形式: #define MAX( a, b) ( (a) &gt; (b) (a) : (b) ) //这里为什么有这么多括号,后面会讲 普通函数形式: int max(int a, int b) { ...

    通过一个比较函数的例子来说明宏函数和普通函数的区别:

    宏函数形式:

    #define MAX( a, b) ( (a) > (b) (a) : (b) ) //这里为什么有这么多括号,后面会讲

    普通函数形式:

    int max(int a, int b)
    {
         return (a > b a : b)
    }

    宏函数

    优点:节省空间(给形参节省)

    缺点:浪费时间(主要浪费在编译时);没有语法检查,不安全。

    普通函数

    优点:有语法检查

    缺点:浪费空间。


    注意宏函数在调用时只是对函数中的变量做简单的替换,注意这里的替换真的是替换,非常死板的那种!!!

    可以看一下下面的例子:

    #define SQUARE_SUM(x,y) x*x+y*y
    #include <stdio.h>
    
    int main()
    {
        int i = 1,j = 2,k ;
        k = SQUARE_SUM(i+1,j);
        printf("%d",k);
        return 0;
    }

    很多人可能会这样算:2*2+2*2=8,这样其实是错误的。

    看一下程序运行的结果:

    原因是程序只是做了替换,也就是1+1*1+1+2*2=7

    现在知道为什么要在宏函数定义时加这么多括号了吧 (= =)

    想达到结果为8的效果应该这样写:

    #define SQUARE_SUM(x,y) (x)*(x)+(y)*(y) //注意这里的括号!!
    #include <stdio.h>
    
    int main()
    {
        int i = 1,j = 2,k ;
        k = SQUARE_SUM(i+1,j);
        printf("%d",k);
        return 0;
    }

    运行结果:

    OK! 大功告成!

    展开全文
  • 为什么要用宏定义函数

    千次阅读 2019-08-01 17:00:36
    代码本身不是函数,但使用起来象函数。 预处理器用复制代码的方式代替函数调用,省去了参数压栈、生成汇编语言的CALL调用、 返回参数、执行return等过程,从而提高了速度。 使用代码最大的缺点是容易出错,预...
  • C++ 宏定义函数(单行和多行)

    千次阅读 2020-06-03 15:11:20
    在软件开发过程中,经常有一些常用或者通用的功能或者代码段,这些功能既可以写成函数,也可以封装成为宏定义。那么究竟是用函数好,还是宏定义好?这就要求我们对二者进行合理的取舍。 宏定义中允许包含两行以上...
  •     要写好C语言,漂亮的宏定义是非常重要的。宏定义可以帮助我们防止出错,提高代码的可移植性和可读性等。  在软件开发过程中,经常有一些常用或者通用的功能或者代...
  • 宏定义函数与普通函数的区别

    千次阅读 2017-10-17 23:23:48
    #define MAX(a,b) ((a)>(b)?(a):(b)) int MAX1(int a,int b) { return a>b?a:b; ...1)宏定义函数没有参数类型也不做类型检查,预编译...2)宏定义函数时一定要注意括号的存在和匹配,有时会因为 括号的不存在就会导致
  • 内联函数的优越性:一:inline定义的类的内联函数函数的代码被放入符号表中,在使用时直接进行替换(像宏定义一样展开),没有了调用的开销,效率很高。二:类的内敛函数是一个真正的函数。三:使用内联函数inline...
  • iOS 使用宏定义函数和代码块

    千次阅读 2018-01-18 10:53:40
    iOS使用宏定义函数和代码块 今天在开发过程中碰到一个问题:就是父类中要向外发送通知,然后子类中或者其他类中来接收它。当然一般是把它写到类方法中去,但是有个问题,就是如果调用的类不是它的子类,就不能直接...
  • 2.编译器会对内联函数的参数类型做安全检查或自动类型转换(同普通函数),而宏定义则不会; 3.内联函数可以访问类的成员变量,宏定义则不能; 4.在类中声明同时定义的成员函数,自动转化为内联函数。文章(一)内联...
  • 内联函数和宏定义函数的区别

    千次阅读 2019-05-17 19:53:55
    1、不同点: 内联函数是在编译时展开,而宏在预编译时展开;在编译的时候,内联函数直接被嵌入到目标代码中去,而宏只是一个简单的文本替换。 ... inline有点类似于宏定义,但是它和宏定义不同...
  • C语言中的宏函数宏定义

    千次阅读 2022-04-01 20:47:56
    3、带参宏定义函数调用的区别 4、头文件中常用的宏定义 5、宏中#和##的用法 从开始写C语言到生成执行程序的流程大致如下: 预处理工作是系统引用预处理程序对源程序中的预处理部分做处理,而预处理部分是指以...
  • 最近在看别人的代码的过程中,发现了宏定义代码,由于自己这块之前没有用过,所以编写了示例程序,学习一下宏定义代码。...那有没有一种更加通用的方式呢,宏定义函数给了我们一种选择,示例如下...
  • c语言宏定义函数如何调用

    千次阅读 2015-09-22 10:20:24
    同样道理,这个宏定义的外层括号也是不能省的。若函数中是宏替换为 ++MAX(a,b),则宏展开就成了 ++(a)>(b)?(a):(b),运算优先级也是错了。  (3)宏函数往往会导致较低的代码执行效率。  int a[]={9,3,5,...
  • 利用宏定义一个函数

    2021-08-18 15:52:19
    } //宏定义一个swap函数 int main() { int x = 1; int y = 2; printf("x=%d,y=%d \n", x,y); SWAP(x,y); printf("x=%d,y=%d \n", x,y); printf("\n"); return 0; } 运行结果: 函数中 形参的值只会..
  • 在软件开发过程中,经常有一些常用或者通用的功能或者代码段,这些功能既可以写成函数,也可以封装成为宏定义。那么究竟是用函数好,还是宏定义好?这就要求我们对二者进行合理的取舍。 宏定义中允许包含两行以上...
  • 关于C语言刷题(#define宏定义函数的常见错误) 首先我们来先看对#define的定义 define,宏定义,C语言中预处理命令一种。分为无参宏定义和带参宏定义。无参宏定义的一般形式为:#define 宏名 字符串;带参宏定义的...
  • 文章目录预处理预处理运算符宏定义无参宏定义带参宏定义宏定义-定义函数 此文主要介绍宏定义,并在介绍宏定义时举例介绍预处理命令 预处理 参考:C 预处理器 | 菜鸟教程 重要的预处理器指令如下: 指令 描述 ...
  • C/C++用宏定义函数

    千次阅读 2019-05-31 21:38:45
    #include "stdio.h" #define ADD \ int add(int a, int b) \ { \ int c = a+b; \ printf("c=%d\n",c); \ return c; \ } namespace ns { ADD; int a = 2; int b = 3;......
  • 函数的区别 属性 #define 函数 代码长度 每次调用时,代码都会被插入到程序中。除了非常小的 之外,程序的长度将大幅增加 函数代码只出现在一个地方,每次调用这个函数时, 调用的...
  • 以符号“#”开头的命令,如: #define N 10; #define <stdio.h>...C编译系统的预处理功能主要包括的处理、文件包含的处理、条件编译的处理三种。所有预处理命令均以“#”开始,末尾不加分号,以区别

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 366,361
精华内容 146,544
关键字:

宏定义函数

友情链接: hmr3000_revB.zip