宏的用法
来源:互联网 发布:勤思教育怎么样知乎 编辑:程序博客网 时间:2024/06/06 00:15
在C语言中使用宏,我们经常这么做,但是为什么使用宏,他可以做什么,我们或许只是一知半解,
下面简单介绍如何在C语言中使用宏预处理器。
#define语句
对于define语句,我们已经非常熟悉,一个宏定义语句,主要用途是定义符号常量,如:
#define PI 3.14159
定义了圆周率PI 为3.14159,在以后用到3.14159的地方直接用PI代替即可,也方便我们编写代码,
更大的好处是,如果我不想将圆周率定为3.14159而要求更高精度,如3.14159265,
则只需将上面的宏定义改为:
#define PI 3.1415926
即可,无需到程序中用到这个值的地方逐一修改。
下面介绍#define的高级应用
A、 带有参数的宏定义语句
我们也可以定义接受参数的符号,如AQUARE:
#define SQUARE(x) x*x
在以后用到SQUARE(a) 是,将会自动用a*a替换,
如SQUARE(3)将被替换成3*3,这个函数的好处是不论x是什么类型,
都可进行同样的处理,double,int类型都可处理,但存在一个问题,如
y=SQUARE(a+1)则将被替换成a+1*a+1
这不是我们想要的结果,所以最好用下面的方法定义
#define SQUARE(x) (x)*(x)
类似可以定义如下函数:
#define MAX(a,b) ((a)>(b))?(a):(b))
B、接受可变参数个数的宏
宏定义同样可以接受可变参数个数的参数列表,为了向预处理器表明我们的宏接受可变参数,
可以在参数列表后面跟上三个点(...),在随后的宏定义表达式中,
我们使用特殊符号__VA_ARGS__来代表具体参数(注意,前后是双下划线),例如我们定义:
#define debugPrintf(...) printf("DEBUG: "__VA_ARGS__)
则可用下面方式使用该宏
debugPrintf("Hello world/n");
或者
debugPrintf("i= %d, j=%d /n",i,j);
输出分别为(加入i=100,j=200):
DEBUG: Hello World
DEBUG: i=100, j=200
C、#操作符
如果我们在参数操作符的前面放置一个#,那么C语言的预处理器将使用该参数生成一个常数字符串,
例如我们定义str如下:
#define str(x) #x
如果在程序中输入语句
str(testing)
最终展开形式将会是
"testing"
而语句 printf(str(Programming in C is fun:/n));将被转换为:
printf("Programming in C is fun:/n");
D、##操作符
在宏定义中,这个操作符可以把两个符号连接起来。##操作符的前面或者后面可以是宏的参数,
预处理器在展开宏的时候,将把该参数和##操作符前面或者后面的符号连接起来,
以便创建一个新的符号。如:
#define printx(n) printf("%d/n", x##n)
语句中的字符串“x##n”的##操作符将前面和后面的记号连接起来,合成一个新的记号,
因此下面的宏调用语句:
printf(20);
将被展开成如下形式:
printf("%i/n",x20);
如果你用过VTK,看过其头文件,你就会发现VTK的头文件中的函数和我们用到的函数不一样,
其实并不是不一样,只是用了宏替换而已,如对球的操作函数-设定球心函数为:
void SetCenter (double, double, double);
但该头文件中的函数声明却是:
vtkGetVectorMacro(Center,double,3);
这里就是用了红替换而将下面的函数展开成上面的函数。
看下面的一个例子:
#include <stdio.h>
#include <malloc.h>
#define setMacro(c,x) set##c(x)
double setx(double a)
{
return a+2.0;
}
double sety(double a)
{
return a;
}
double *setxyz(double a)
{
double arr[3];
arr[0]=a+4.0;
arr[1]=a+5.0;
arr[2]=a+6.0;
return arr;
}
int main(int argc,char *argv[])
{
double a=5.0;
double b=setMacro(x,a);//等价于 b=setx(a);
double c=setMacro(y,a);//
printf("a=%lf/nb=%lf/nc=%lf/n",a,b,c);
double *xyz=malloc(3*sizeof(double));
xyz=setMacro(xyz,a);
printf("arr[0]=%f,arr[1]=%f,arr[2]=%f/n",xyz[0],xyz[1],xyz[2]);
return 0;
}
编译后执行的输出结果为:
a=5.000000
b=7.000000
c=5.000000
arr[0]=9.000000,arr[1]=10.000000,arr[2]=11.000000
上面的函数只要遇到setMacro(c,x)就将其替换成setc(x)的形式,并且不分析参数x的类型如何,
如setMacro(x,a) 被替换成setx(a),setMacro(xyz,a)被替换成setxyz(a)执行。
当然了,你或许会说上面的代码不规范,的确,我只是作为一个例子拿过来用而已,
说明如何使用宏替换函数。
宏处理语句的用法还有:#include 语句、条件编译语句(如#ifdef、#enif、#else和#ifndef语句)、
#if和elif、#undef语句等,这里就不一一说明。
- 宏的用法
- C宏的用法
- #define 宏的用法
- 宏 # ##符号 的用法
- 宏的用法
- 宏#line的用法
- offsetof宏的用法
- 宏的用法
- 宏的用法
- TEMP_FAILURE_RETRY宏的用法
- define宏的用法
- 宏的基本用法
- 宏 #define 的用法
- stdarg宏的用法
- 宏的高级用法# ##
- assert宏的用法
- 宏的几个绝妙用法
- 宏中"#"和"##"的用法
- jre与jdk的区别
- IE插件
- 敏捷开发中的架构设计
- 获取本机ipv4网卡地址
- use: device not found, try 'modprobe fuse' first
- 宏的用法
- javascript获取页面、屏幕大小
- Exception in thread "main" java.lang.NoClassDefFoundError
- 不老神仙软件开发感悟 (转)
- 小学期正式开始
- GCC版本导致的Floating Point Exception
- windows 系统端口不通,改不了IP(麦咖啡mac)
- android应用的启动流程
- 硬链接和软链接的区别