完整目录、平台简介、安装环境及版本:参考《21天学C++ 概览》
二一、进一步掌握的内容
21.1 预处理和预编译
21.1.1 #include:运行编译时,预处理器先运行
预处理器查找预处理指令,即以”#”开头的指令,用来改变源代码的文本,生成新的源文件(临时文件);
#include指示预处理器查找其后文件并将文件写入该位置;
21.1.2 #define:定义字符串替换,如#define BIG 512
只是预处理器在任何看到BIG的地方用字符串512替换;
如int myArray[BIG];预处理器长生的中间文件是int myArray[512];
使用define可以替换常熟,但由于define直接替换不做类型检查,所以关键字const比denfine有优势;
21.1.3 编译器预定义了大量有用的宏,如_DATE_、_TIME_等两条下划线
21.1.4 #ifdef #ifndef #endif
#ifdef DemoVersion
...;
#endif
#ifdef DemoVersion
...;
#else
...;
#endif
#ifndef SW_VERSION
....;
#endif
#ifndef SW_VERSION
....;
#else
....;
#endif
#define DemoVersion
#define SW_VERSION 5
#include <iostream>
using std::endl;
using std::cout;
int main()
{
#ifdef DemoVersion
cout << "DemoVersion defined." << endl;
#else
cout << "DemoVersion not defined." << endl;
#endif
#ifndef SW_VERSION
cout << "SW_VERSION not defined!" << endl;
#else
cout << "SW_VERSION defined as: "
<< SW_VERSION << endl;
#endif
#ifdef WINDOWS_VERSION
cout << "WINDOWS_VERSION defined!" << endl;
#else
cout << "WINDOWS_VERSION was not defined." << endl;
#endif
cout << "Done." << endl;
return 0;
}
执行结果如下:
DemoVersion defined.
SW_VERSION defined as: 5
WINDOWS_VERSION was not defined.
Done.
请按任意键继续. . .
21.1.5 避免头文件重复包含
#ifndef _FILE_H
#define _FILE_H
//file.h文件内容
#endfi
第一次调用时,没有定义头文件宏,接着定义并包含头文件。第二次调用时,由于第一次已经定义了头文件宏,所以直接跳转到#endif
#ifndef _FILE1_H
#define _FILE1_H
#include <iostream>
using namespace std;
void file1(){
cout<<"file1 "<<endl;
}
#endif
#ifndef _FILE2_H
#define _FILE2_H
#include <iostream>
#include "file1.h"
using namespace std;
void file2(){
cout<<"file2 ";
file1();
}
#endif
#include <iostream>
using namespace std;
#include "file1.h"
#include "file2.h"
int main(){
cout<<"main "<<endl;
file2();
file1();
return 0;
}
执行结果如下:
main
file2 file1
file1
请按任意键继续. . .
21.2 宏函数
#define可以创建宏函数,直接进行替换
#define TWICE(X) ((X)*2) //倍数
#define MAX(x,y) ((x)>(y)?(x):(y)) //取两个值的最大值
#define MIN(x,y) ((x)<(y)?(x):(y)) //取两个值的最小值
#define宏函数为总要用括号
括号可以避免不必要的副作用,特别是在传递复杂表达式的情况下
#define 存在最大的问题就是类型安全问题
#include <iostream>
using namespace std;
#define CUBE(a) ( (a) * (a) * (a) )
#define THREE(a) a * a * a
int main()
{
long x = 5;
long y = CUBE(x);
long z = THREE(x);
cout << "y: " << y << endl;
cout << "z: " << z << endl;
long a = 5, b = 7;
y = CUBE(a+b);
z = THREE(a+b);
cout << "y: " << y << endl;
cout << "z: " << z << endl;
return 0;
}
执行结果如下:
y: 125
z: 125
y: 1728
z: 82
请按任意键继续. . .
21.3 内联函数inline
经常声明内联函数而不是宏
代码替换,不会发生函数调用的系统开销
#include <iostream>
using namespace std;
inline unsigned long Square(unsigned long a) { return a * a; }
inline unsigned long Cube(unsigned long a)
{ return a * a * a; }
int main()
{
unsigned long x=1 ;
for (;;)
{
cout << "Enter a number (0 to quit): ";
cin >> x;
if (x == 0)
break;
cout << "You entered: " << x;
cout << ". Square(" << x << "): ";
cout << Square(x);
cout<< ". Cube(" << x << "): ";
cout << Cube(x) << "." << endl;
}
return 0;
}
执行结果如下:
Enter a number (0 to quit): 3
You entered: 3. Square(3): 9. Cube(3): 27.
Enter a number (0 to quit): 2
You entered: 2. Square(2): 4. Cube(2): 8.
Enter a number (0 to quit): 0
请按任意键继续. . .
21.4 assert()
assert()
- 参数值为TRUE时,返回TRUE;
- 参数值为FALSE时,则执行某种操作;如终止程序或抛出异常;
- 开发过程中很有帮助,只有在DEBUG模式下起作用;
- 开发过程中很有帮助,在RELEASE产品形成时不会有性能损失,也不会增加可执行文件的大小;
assert()与异常
- assert不能处理运行时的错误条件,如错误数据、内存不足、不能打开文件等;
- assert只能捕捉编程错误,即如果assert提示了,则说明代码中有一个bug;
- 在正式发布的版本中assert会自动隐藏,不能指望assert处理运行时问题,因为assert已经不存在了;
assert()副作用
- 当向进行值测试时,如ASSERT(x==5);本来是想测试是否等于5,结果成一个难发现的BUG;
#define DEBUG
#include <iostream>
using namespace std;
#ifndef DEBUG
#define ASSERT(x)
#else
#define ASSERT(x) \
if (! (x)) \
{ \
cout << "ERROR!! Assert " << #x << " failed" << endl; \
cout << " on line " << __LINE__ << endl; \
cout << " in file " << __FILE__ << endl; \
}
#endif
int main()
{
int x = 5;
cout << "First assert: " << endl;
ASSERT(x==5);
cout << "\nSecond assert: " << endl;
ASSERT(x != 5);
cout << "\nDone." << endl;
return 0;
}
执行结果如下:
First assert:
Second assert:
ERROR!! Assert x != 5 failed
on line 24
in file e:\study\source\c++\21005_assert\main.cpp
Done.
请按任意键继续. . .
21.5 打印中间值DEBUG
除了assert外,如果想打印指针、变量、字符串的当前值
#include <iostream>
using namespace std;
#define DEBUG
#ifndef DEBUG
#define PRINT(x)
#else
#define PRINT(x) \
cout << #x << ":\t" << x << endl;
#endif
enum BOOL { FALSE, TRUE } ;
int main()
{
int x = 5;
long y = 73898l;
PRINT(x);
for (int i = 0; i < x; i++)
{
PRINT(i);
}
PRINT (y);
PRINT("Hi.");
int *px = &x;
PRINT(px);
PRINT (*px);
return 0;
}
执行结果如下:
x: 5
i: 0
i: 1
i: 2
i: 3
i: 4
y: 73898
"Hi.": Hi.
px: 012FFBBC
*px: 5
请按任意键继续. . .