前面教程汇总
第一讲
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
#include <iostream>
using namespace std;
int main()
{
cout << "圆周率约等于" << PI << endl;
return 0;
}
输出结果:
3.14
宏语句
我们还可以用宏定义一条或多条语句。例如:
#include <cstdio>
#define Print printf("hello world!")
using namespace std;
int main()
{
Print;
return 0;
}
宏函数
我们还可以用宏来定义函数。宏定义也可以带参数,例如:
#include <cstdio>
#define Print(str) printf("%s",str)
using namespace std;
int main()
{
Print("这是一个只有一条语句的宏函数!");
return 0;
}
#undef 指令
#undef 是用来撤销宏定义的,用法如下:
#define PI 3.141592654
...
#undef PI
ifndef 指令
使用 ifndef 防止头文件被重复包含和编译。这是宏定义的一种,它可以根据是否已经定义了一个变量来进行分支选择,一般用于调试等等.实际上确切的说这应该是预处理功能中三种(宏定义,文件包含和条件编译)中的一种----条件编译。 C语言或C++在对程序进行编译时,会先根据预处理命令进行“预处理”。C语言和C++的编译系统包括预处理,编译和链接等部分。
#ifndef x
#define x
...
...
...
#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
#define xxx
#endif
这个用法主要是在头文件中,主要是为了防止类重复的 include ,所以在类的头文件之前加上前面两个,用类名替代 xxx ,在最后加上最后一句。
宏定义相关作用符
换行符 \
我们定义宏语句或者宏函数时不可能总是一条语句呀,那要是有很多条语句时怎么办?都写在一行吗?这样显然代码就不美观,可读性不好。所以有多条语句时,我们就在每行末尾(除了最后一行)加上 \ ,代表换行的意思。 例如:
#include <cstdio>
#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 <cstdio>
#define Print(str)\
{\
printf(#str"的值是%d",str);\
}
using namespace std;
int main()
{
int x=3,y=4;
Print(x+y);
return 0;
}
片段连接符 ##
## 是一种分隔连接方式,它的作用是先分隔,然后进行强制连接。在普通的宏定义中,预处理器一般把空格解释成分段标志,对于每一段和前面比较,相同的就被替换。但是这样做的结果是,被替换段之间存在一些空格。如果我们不希望出现这些空格,就可以通过添加一些 ## 来替代空格。 例:
#include <cstdio>
#define Add(n,value)\
{\
num##n+=value;\
}
using namespace std;
int main()
{
int num1=1;
int num2=10;
Add(2,10);
printf(" num1=%d\n num2=%d",num1,num2);
return 0;
}
关于宏的内容还有很多,需要大家慢慢摸索,这里我就不再过多的介绍了(因为我不是特别喜欢用宏,喜欢用普通的 const 常量和函数等,因为它会无视很多限制,所以在大型场合下人们都会说宏是一种危险的东西)。注意,这只是入门教程,目的是让人们熟悉C++(因为我写的内容里面有很多带有C语言味,比如我总是用 printf ,而且我也C语言写惯了,所以大家也应该会熟悉C语言),而不是精通C和C++。我也不是C和C++方面的专家(特别厉害的),所以想要深入学习,还是得请大咖(非常无奈)。但是我为了教大家C++投入了很多时间,所以如果能得到你们的赞,那就太好了。
本文完。
|