C++入门教程(十一、宏)-创新互联
- 前面教程汇总
- 第一讲
- 第二讲
- 第三讲
- 第四讲
- 第五讲
- 第六讲
- 第七讲
- 第八讲
- 第九讲
- 第十讲
- 宏
- 什么是预处理?
- 宏定义
- 宏常量
- 宏语句
- 宏函数
- `#undef` 指令
- `ifndef` 指令
- 宏定义相关作用符
- 换行符 `\`
- 字符串化符 `#`
- 片段连接符 `##`
C++入门教程(一、初步了解)
第二讲C++入门教程(二、基本数据类型)
第三讲C++入门教程(三、数组、注释与函数)
第四讲C++入门教程(四、运算符与表达式)
第五讲C++入门教程(五、数组与字符串)
第六讲C++入门教程(六、指针)
第七讲C++入门教程(七、结构体)
第八讲C++入门教程(八、枚举类型)
第九讲C++入门教程(九、语句与控制流)
第十讲C++入门教程(十、联合体)
宏 什么是预处理?编译一个C语言或C++程序的第一步骤就是预处理阶段,这一阶段就是宏发挥作用的阶段。C和C++的预处理器在源代码编译之前对其进行一些文本性质的操作,主要任务包括删除注释、插入被#include
进来的文件内容、定义和替换由#define
定义的符号以及确定代码部分内容是否根据条件编译(#if
)来进行编译。“文本性质”的操作,就是指一段文本替换成另外一段文本,而不考虑其中任何的语义内容。宏仅仅是在C预处理阶段的一种文本替换工具,编译完之后对二进制代码不可见
很简单,格式是#define Object number
,比如定义一个π的值:
#define PI 3.14
可以直接用:
#define PI 3.14
#includeusing namespace std;
int main()
{cout<< "圆周率约等于"<< PI<< endl;
return 0;
}
输出结果:
3.14
宏语句我们还可以用宏定义一条或多条语句。例如:
#include#define Print printf("hello world!")
using namespace std;
int main()
{Print; //预处理时会被替换为 printf("hello world!");
return 0;
}
宏函数我们还可以用宏来定义函数。宏定义也可以带参数,例如:
#include#define Print(str) printf("%s",str)
using namespace std;
int main()
{Print("这是一个只有一条语句的宏函数!");
//预处理时会被替换为 printf("%s","这是一个只有一条语句的宏函数!")
return 0;
}
#undef
指令#undef
是用来撤销宏定义的,用法如下:
#define PI 3.141592654
...
// code
#undef PI
//下面开始 PI 就失效了
ifndef
指令使用ifndef
防止头文件被重复包含和编译。这是宏定义的一种,它可以根据是否已经定义了一个变量来进行分支选择,一般用于调试等等.实际上确切的说这应该是预处理功能中三种(宏定义,文件包含和条件编译)中的一种----条件编译。 C语言或C++在对程序进行编译时,会先根据预处理命令进行“预处理”。C语言和C++的编译系统包括预处理,编译和链接等部分。
#ifndef x //先测试x是否被宏定义过
#define x //如果没有宏定义下面就宏定义x并编译下面的语句
...
...
...
#endif //如果已经定义了则编译#endif后面的语句
条件指示符#ifndef
检查预编译常量在前面是否已经被宏定义。如果在前面没有被宏定义,则条件指示符的值为真,于是从#ifndef
到#endif
之间的所有语句都被包含进来进行编译处理。相反,如果#ifndef指示符的值为假,则它与#endif
指示符之间的行将被忽略。条件指示符#ifndef
的最主要目的是防止头文件的重复包含和编译。
千万不要忽略了头文件的中的#ifndef
,这是一个很关键的东西。比如你有两个C(或C++)文件,这两个C(或C++)文件都include
了同一个头文件。而编译时,这两个C(或C++)文件要一同编译成一个可运行文件,于是问题来了,大量的声明冲突。
所以还是把头文件的内容都放在#ifndef
和#endif
中吧。不管你的头文件会不会被多个文件引用,你都要加上这个。一般格式是这样的:
#ifndef<标识>#define<标识>...
#endif
<标识>
在理论上来说可以是自由命名的,但每个头文件的这个“标识”都应该是唯一的。标识的命名规则一般是头文件名全大写,前后加下划线,并把文件名中的“.”也变成下划线,如(这里以C语言举例子,因为这一讲的内容同时适用于C和C++):stdio.h
#ifndef _STDIO_H_
#define _STDIO_H_
......
#endif
#ifndef xxx //如果没有定义xxx
#define xxx //定义xxx
#endif //结束如果
这个用法主要是在头文件中,主要是为了防止类重复的include
,所以在类的头文件之前加上前面两个,用类名替代xxx
,在最后加上最后一句。
\
我们定义宏语句或者宏函数时不可能总是一条语句呀,那要是有很多条语句时怎么办?都写在一行吗?这样显然代码就不美观,可读性不好。所以有多条语句时,我们就在每行末尾(除了最后一行)加上\
,代表换行的意思。
例如:
#include#define Print printf("这是第1条语句\n");\
printf("这是第2条语句\n");\
printf("这是第3条语句\n")
#define Show(str1,str2,str3)\
{\
printf("%s\n",str1);\
printf("%s\n",str2);\
printf("%s\n",str3);\
}
using namespace std;
int main()
{Print; //无参数宏函数
Show("first","second","third"); //带参数宏函数
return 0;
}
字符串化符#
#
是“字符串化”的意思,将出现在宏定义中的#
是把跟在后面的参数转换成一个字符串。
例如:
#include#define Print(str)\
{\
printf(#str"的值是%d",str);\
}
using namespace std;
int main()
{int x=3,y=4;
Print(x+y); //此处等价于printf("x+y""的值是%d",x+y);
//#str等价于"x+y",所以#str不需要再用双引号引起来
return 0;
}
片段连接符##
##
是一种分隔连接方式,它的作用是先分隔,然后进行强制连接。在普通的宏定义中,预处理器一般把空格解释成分段标志,对于每一段和前面比较,相同的就被替换。但是这样做的结果是,被替换段之间存在一些空格。如果我们不希望出现这些空格,就可以通过添加一些##
来替代空格。
例:
#include#define Add(n,value)\
{\
num##n+=value;\
}
using namespace std;
int main()
{int num1=1;
int num2=10;
Add(2,10); //等价于num2+=10; 这里把num和2连接成了num2
printf(" num1=%d\n num2=%d",num1,num2);
return 0;
}
关于宏的内容还有很多,需要大家慢慢摸索,这里我就不再过多的介绍了(因为我不是特别喜欢用宏,喜欢用普通的const
常量和函数等,因为它会无视很多限制,所以在大型场合下人们都会说宏是一种危险的东西)。注意,这只是入门教程,目的是让人们熟悉C++(因为我写的内容里面有很多带有C语言味,比如我总是用printf
,而且我也C语言写惯了,所以大家也应该会熟悉C语言),而不是精通C和C++。我也不是C和C++方面的专家(特别厉害的),所以想要深入学习,还是得请大咖(非常无奈)。但是我为了教大家C++投入了很多时间,所以如果能得到你们的赞,那就太好了。
本文完。
你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧
新闻名称:C++入门教程(十一、宏)-创新互联
标题路径:http://scjbc.cn/article/pcdjh.html